我有一個用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