我使用java.util.logging
的標準ConsoleHandler
,默認情況下控制檯輸出指向錯誤流(即System.err
)。如何將std err的java日誌控制檯輸出更改爲stdout?
如何將控制檯輸出更改爲輸出流(即System.out
)?
我使用java.util.logging
的標準ConsoleHandler
,默認情況下控制檯輸出指向錯誤流(即System.err
)。如何將std err的java日誌控制檯輸出更改爲stdout?
如何將控制檯輸出更改爲輸出流(即System.out
)?
看看的文檔和來源 - 我相信你可以輕鬆地編寫一個只使用System.err而不是System.out的版本。 (可惜的是ConsoleHandler不允許這樣配置,說實話)
然後,它只是配置日誌記錄系統以正常方式使用新的StdoutHandler(或任何您稱之爲的)的情況。
如果使用Java記錄,您可以更改默認的處理程序:
例如,對於文件: 處理器FH =新的FileHandler(文件名); Logger.getLogger(LOGGER_NAME).addHandler(fh);
如果你想輸出到一個流,你可以使用StreamHandler,我認爲你可以配置任何你喜歡的輸出流,包括系統流。
我想出了一種方法。首先刪除默認的控制檯處理程序:
setUseParentHandlers(false);
然後子類ConsoleHandler並在構造:
setOutputStream(System.out的);
爲了避免在下次調用`setOutputStream(...)`或`LogManager.reset()`時關閉它,你最好使用自實現的`OutputStream`封裝`System.out`。 – amotzg 2012-09-27 03:54:24
另外,請小心不要調用(ConsoleHandler`的超級構造函數),因爲它設置System.err,並在調用`setOutputStream(System.out)`時關閉它。或者,您可以繼承`StreamHandler`並調用`super(OutputStream,Formatter)`。 – amotzg 2012-09-27 03:58:00
如果你設置了setUseParentHandlers(false);只有這個班級設置了它。應用中的其他課程仍然會將其傳遞給stderr。
如果有人爲根日誌記錄類(Logger.GLOBAL_LOGGER_NAME)執行此操作,則將禁用所有類的控制檯日誌記錄。 – koppor 2012-11-17 20:44:12
在構造函數調用Super(System.out,)中簡單地擴展StreamHandler &。這將避免關閉System.err的 - 感謝
Handler consoleHandler = new Handler(){
@Override
public void publish(LogRecord record)
{
if (getFormatter() == null)
{
setFormatter(new SimpleFormatter());
}
try {
String message = getFormatter().format(record);
if (record.getLevel().intValue() >= Level.WARNING.intValue())
{
System.err.write(message.getBytes());
}
else
{
System.out.write(message.getBytes());
}
} catch (Exception exception) {
reportError(null, exception, ErrorManager.FORMAT_FAILURE);
}
}
@Override
public void close() throws SecurityException {}
@Override
public void flush(){}
};
但是,在現代...有沒有辦法做到這一點,而不實施自定義處理程序? – Victor 2013-08-25 20:19:56
我來到
SimpleFormatter fmt = new SimpleFormatter();
StreamHandler sh = new StreamHandler(System.out, fmt);
logger.addHandler(sh);
的腳幾次嗯,我剛剛得到位,試圖完成這一壯舉。在Google之前,我設法召喚下面的黑客。醜陋,但它似乎完成了工作。
public class StdoutConsoleHandler extends ConsoleHandler {
protected void setOutputStream(OutputStream out) throws SecurityException {
super.setOutputStream(System.out); // kitten killed here :-(
}
}
當心:調用setOutputStream()從構造函數是誘人的,但它確實(如喬恩斯基特已經指出的)密切System.err的。瘋狂的技能!
如果仍然有人在那裏尋找解決這個問題的方法。 下面是我最後想到的:我只是繼承了StreamHandler並添加了一個額外的參數 MaxLevel,它在publish()的開頭被選中。如果日誌事件的級別大於MaxLevel,則不會再執行發佈。 下面是詳細信息:
MaxlevelStreamHandler.java 主要下方類。
package helper;
/**
* The only difference to the standard StreamHandler is
* that a MAXLEVEL can be defined (which then is not published)
*
* @author Kai Goergen
*/
import java.io.PrintStream;
import java.util.logging.Formatter;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.StreamHandler;
public class MaxlevelStreamHandler extends StreamHandler {
private Level maxlevel = Level.SEVERE; // by default, put out everything
/**
* The only method we really change to check whether the message
* is smaller than maxlevel.
* We also flush here to make sure that the message is shown immediately.
*/
@Override
public synchronized void publish(LogRecord record) {
if (record.getLevel().intValue() > this.maxlevel.intValue()) {
// do nothing if the level is above maxlevel
} else {
// if we arrived here, do what we always do
super.publish(record);
super.flush();
}
}
/**
* getter for maxlevel
* @return
*/
public Level getMaxlevel() {
return maxlevel;
}
/**
* Setter for maxlevel.
* If a logging event is larger than this level, it won't be displayed
* @param maxlevel
*/
public void setMaxlevel(Level maxlevel) {
this.maxlevel = maxlevel;
}
/** Constructor forwarding */
public MaxlevelStreamHandler(PrintStream out, Formatter formatter) {
super(out, formatter);
}
/** Constructor forwarding */
public MaxlevelStreamHandler() {
super();
}
}
主類
中現在顯示在標準輸出的一些事件和一些在標準錯誤,只是創建了兩個StreamLoggers,一個關鍵的事件,一個用於所有其他的,和禁用標準控制檯記錄器:
// setup all logs that are smaller than WARNINGS to stdout
MaxlevelStreamHandler outSh = new MaxlevelStreamHandler(System.out, formatter);
outSh.setLevel(Level.ALL);
outSh.setMaxlevel(Level.INFO);
logger.addHandler(outSh);
// setup all warnings to stdout & warnings and higher to stderr
StreamHandler errSh = new StreamHandler(System.err, formatter);
errSh.setLevel(Level.WARNING);
logger.addHandler(errSh);
// remove default console logger
logger.setUseParentHandlers(false);
logger.info("info");
logger.warning("warning");
logger.severe("severe");
希望這有助於!
更新:我在super.publish()之後添加了super.flush(),以確保消息立即顯示。之前,我遇到了日誌消息總是顯示在最後的問題。它現在是上面代碼的一部分。
我有一個類似的問題。我想記錄信息及以下至System.out
,警告及以上至System.err
。下面是我實現的解決方案:
public class DualConsoleHandler extends StreamHandler {
private final ConsoleHandler stderrHandler = new ConsoleHandler();
public DualConsoleHandler() {
super(System.out, new SimpleFormatter());
}
@Override
public void publish(LogRecord record) {
if (record.getLevel().intValue() <= Level.INFO.intValue()) {
super.publish(record);
super.flush();
} else {
stderrHandler.publish(record);
stderrHandler.flush();
}
}
}
當然,你可以把通過分解出硬編碼引用Level.INFO
,例如,它更加靈活。但是,這對我獲得一些基本的雙流日誌很有幫助。 (順便提一句,關於不通過子控制ConsoleHandler避免關閉System.err
的提示非常有用。)
ConsoleHandler將在構建過程中抓取System.err
的快照。一種選擇是將全局錯誤流與全局輸出流交換,然後創建ConsoleHandler。
final PrintStream err = System.err;
System.setErr(System.out);
ConsoleHandler h = new ConsoleHandler(); //Snapshot of System.err
System.setErr(err);
這假設代碼有權修改錯誤流,並且沒有其他正在運行的代碼正在訪問錯誤流。總之,這是一個選擇,但有更安全的選擇。
當我們創建一個新的ConsoleHandler對象時,默認輸出流是「system.err」。可悲的是,Java並沒有爲ConsoleHandler類提供任何公共方法來設置輸出流。所以它只能在創建對象時設置。由於ConsoleHandler類擴展了StreamHandler,它具有一個受保護的方法「setOutputStream」來顯式設置輸出流。要爲ConsoleHandler設置輸出Stream,只需在新的對象創建調用時重寫此方法即可。
ConsoleHandler consoleHandler = new ConsoleHandler(){
@Override
protected synchronized void setOutputStream(OutputStream out) throws SecurityException {
super.setOutputStream(System.out);
}
};
我認爲ConsoleHandler是默認的,有一個StreamHandler可以打印到任何其他流。 – Uri 2008-10-11 15:30:13
是的,但你想要子類化StreamHandler,以避免嘗試關閉System.err,我懷疑。 – 2008-10-11 17:59:22