使用自己的记录器

时间:2017-04-17 13:08:23

标签: java logging java.util.logging system.out

我创建了自己的小记录器而不是System.out.println

LogManager.getLogManager().reset();
logger = Logger.getLogger(this.toString());
logger.setLevel(loglevel);
Formatter formatter = new Formatter() {
    public String format(LogRecord record) {
        return new Date().toString().substring(11, 20) + record.getLevel()+" " + formatMessage(record) + System.getProperty("line.separator");
    }
};
logger.addHandler(new StreamHandler(System.out, formatter));
LogManager.getLogManager().addLogger(logger);

此时,消息不会被刷新,因此只有在应用程序终止后才会显示。有没有办法在打印出来后刷新消息而不创建新类或添加多行代码?我想保持这段代码尽可能短......

1 个答案:

答案 0 :(得分:2)

问题在于StreamHandler.setOutputStream根据OutputStreamWriterjavadocs中的给定流包裹起来:

  

在写入底层输出流之前,生成的字节在缓冲区中累积。可以指定此缓冲区的大小,但默认情况下,它足以满足大多数用途。

因此无法调用StreamHandler.flush强制将这些字节强制到控制台。

由于您不想创建新类,因此可以使用将ConsoleHandler刷新到控制台,但默认情况下会写入错误流。如果你没有通过执行以下任何其他线程来解决这个问题:

//Global resource so ensure single thread.
final PrintStream err = System.err;
System.setErr(System.out);
try {
    ConsoleHandler ch = new ConsoleHandler();
    ch.setFormatter(formatter);
    logger.addHandler(ch);
} finally {
    System.setErr(err);
}

子类确实是您最好的选择,因为您可能会通过System.outHandler.close()致电LogManager.getLogManager().reset()来意外关闭StreamHandler.setOutputStream,这意味着您不会看到任何输出。

public class OutConsoleHandler extends StreamHandler {
    public OutConsoleHandler(OutputStream out, Formatter f) {
        super(out, f);
    }

    @Override
    public synchronized void publish(LogRecord record) {
        super.publish(record);
        flush();
    }

    @Override
    public void close() throws SecurityException {
        flush();
    }
}