4

我有一个用 Java 写入标准输出的库。我想使用 log4j 在日志中捕获此输出。(我没有编写这个库,所以我无法控制库中的代码)。

是否有捷径可寻?System.setOut 是正确的方法吗?我将什么传递给 System.setOut?

另外,您将如何在 .NET/C# 中执行此操作?

4

5 回答 5

5

一种解决方案是子类化OutputStream. 您只需执行write( int b ). 然后在构造函数中创建PrintStream一个OutputStream

它可能看起来像:

public class L4JOS extends OutputStream {
  logger = Logger.getLogger( "std.out" );
  private int lineEnd = (int)'\n';
  private ByteArrayOutputStream baos = new ByteArrayOutputStream();

  public void write( int b ) throws IOException {
    baos.write( b );
    if ( b == lineEnd ) {
      logger.info( baos.toString() );
      baos.reset();
    }
  }

}

如果它是多线程的,那么你有更多的工作。并确保 appender 不会转到 System.out。

于 2009-02-23T16:45:23.157 回答
2

您可以实现自己的 OutputStream,它只将输出的任何内容记录到 log4j,然后将用户 System.setOut 记录到该 OutputStream 的实例。

请注意,在 log4j 在标准输出上输出内容的情况下,这可能会导致无限循环。

因此,您可能应该进行一些过滤以确定要传递给 log4j 的内容以及传递给原始 stdout 流的内容

于 2009-02-23T16:47:06.523 回答
0

你为什么想这么做。您不应该直接写入 sysout,如果要输出到 sysout,则应该写入 log4j 并配置控制台附加程序。

于 2009-02-23T16:20:29.410 回答
0

您应该能够将 GUI 应用程序电锯连接到标准输出并获得所需的结果。

于 2009-02-23T16:21:14.370 回答
0

我不想使用 setOut() 因为它是一个全局变量。你会遇到“远距离行动”:你只想为这个库截取标准输出,而不是践踏任何可能需要使用标准输出的东西。

如果可能,请在单独的进程空间中运行调用库函数的代码;然后您可以编写一个线程,从该进程读取标准输出并发送到记录器。

new Thread() {
  public void run() {
    ProcessBuilder pb = new ProcessBuilder(command);
    Process p = pb.start();
    BufferedReader in = new BufferedReader(p.getInputStream());
    String line;
    while ((line = in.readLine()) != null) {
      log.info(line);
      // or you could parse line and try to dynamically pick a log level
    }
  }
}

您需要一种很好的方法来将被调用进程的输出返回给调用者,但如果它像返回一个值一样简单,那么应该很容易将它作为 stdout 的最后一行或一行返回一个特殊的信号代码,什么的。

于 2009-05-27T19:06:39.300 回答