2009-02-23 118 views
4

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

有没有简单的方法来做到这一点? System.setOut是否正确?我传递给System.setOut的是什么?

另外,你将如何在.NET/C#中做到这一点?

回答

3

一个解决方案是子类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。

0

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

+0

我没有写这个库,我只是用它,我想捕获它产生的输出。 – 2009-02-23 16:23:18

+1

upvoted,因为它可能会导致其他人在一条直线上,虽然它不是解决手头问题的正确方法。 – 2013-04-02 11:46:02

0

您应该能够将GUI应用程序chainsaw连接到标准输出列表并获得您需要的结果。

2

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

请注意,在log4j输出标准输出内容时,这可能会导致无限循环。

所以,你应该做一些过滤,以确定哪些传递给log4j的,什么要传递到原来的标准输出流

0

我不喜欢用专列(),因为它是一个全局变量。你会遇到“远处行动”:你想为这个库拦截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,或者一个带有特殊信号代码的行,或者其他的东西。

相关问题