2009-02-23 70 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,或者一個帶有特殊信號代碼的行,或者其他的東西。

相關問題