我使用的标准ConsoleHandler
,从java.util.logging
和由默认控制台输出被引导到错误流(即System.err
).
如何将控制台输出更改为输出流(即System.out
)?
我到了
SimpleFormatter fmt = new SimpleFormatter(); StreamHandler sh = new StreamHandler(System.out, fmt); logger.addHandler(sh);
我想出了一个方法.首先删除默认控制台处理程序:
setUseParentHandlers(假);
然后继承ConsoleHandler并在构造函数中:
setOutputStream(System.out的);
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(){} };
嗯,我只是踩了几下脚,试图完成这个壮举.在谷歌搜索之前,我设法让人想到以下黑客.丑陋,但它似乎完成了工作.
public class StdoutConsoleHandler extends ConsoleHandler { protected void setOutputStream(OutputStream out) throws SecurityException { super.setOutputStream(System.out); // kitten killed here :-( } }
注意:从构造函数调用setOutputStream()很有吸引力,但它确实(正如Jon Skeet已经指出的那样)关闭了System.err.疯狂的技能!
我有一个类似的问题。我想将INFO及以下版本登录到System.out
,并将WARNING及以上版本登录到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
非常有用。)