我有一个用Java写入标准输出的库。我想用log4j在日志中捕获这个输出。 (我没有写这个库,所以我无法控制库中的代码)。在log4j/log4net中捕获标准输出
有没有简单的方法来做到这一点? System.setOut是否正确?我传递给System.setOut的是什么?
另外,你将如何在.NET/C#中做到这一点?
我有一个用Java写入标准输出的库。我想用log4j在日志中捕获这个输出。 (我没有写这个库,所以我无法控制库中的代码)。在log4j/log4net中捕获标准输出
有没有简单的方法来做到这一点? System.setOut是否正确?我传递给System.setOut的是什么?
另外,你将如何在.NET/C#中做到这一点?
一个解决方案是子类OutputStream
。您只需执行write(int b)
。然后用构造函数中的OutputStream
创建一个PrintStream
。
它可能看起来像:
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。
你为什么想要这样做。您不应直接写入sysout,如果要输出到sysout,则应该写入log4j并配置控制台appender。
您应该能够将GUI应用程序chainsaw连接到标准输出列表并获得您需要的结果。
你可以实现你自己的OutputStream,它只记录log4j的任何内容,然后将用户System.setOut记录到该OutputStream的一个实例。
请注意,在log4j输出标准输出内容时,这可能会导致无限循环。
所以,你应该做一些过滤,以确定哪些传递给log4j的,什么要传递到原来的标准输出流
我不喜欢用专列(),因为它是一个全局变量。你会遇到“远处行动”:你想为这个库拦截stdout,但不要践踏其他任何可能需要使用stdout的东西。
如果可能,请在独立的进程空间中运行调用库函数的代码;那么你可以编写一个线程,从该进程读取stdout并发送给记录器。
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-02-23 16:23:18
upvoted,因为它可能会导致其他人在一条直线上,虽然它不是解决手头问题的正确方法。 – 2013-04-02 11:46:02