我正在尝试实现一个自定义处理程序,将解析后的LogRecord
个对象记录到一个文件中(基本上是FileHandler
或StreamHandler
所做的)。我目前的实施如下所示:
public final class ErrorHandler extends Handler {
private static final String OUTPUT_FILE = ".output";
private final Formatter formatter = new CustomFormatter();
private BufferedWriter writter;
@Override
public void publish(LogRecord record) {
if (record.getLevel() == SEVERE || record.getLevel() == WARNING) {
writeToOutput(record);
}
}
void writeToOutput(LogRecord log) {
try {
if (writter == null) {
writter = new BufferedWriter(new FileWriter(OUTPUT_FILE, true));
}
writter.write(formatter.format(log));
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void flush() {
}
@Override
public void close() {
try {
writter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
PS:我知道我们可以通过在FileHandler
或StreamHandler
上设置过滤器和格式化程序来实现与上面的代码相同的功能,但是我将来会需要使用挂钩点的
我的问题是,如果我在没有实现的情况下离开flush()
,虽然创建了输出文件但是没有写入日志。如果我在writter.flush()
内调用flush()
,则会重复日志。虽然这可能发生了什么?
答案 0 :(得分:0)
我的问题是,如果我没有实现执行flush(),虽然创建了输出文件,但是没有写入日志。
这是因为字节缓存在BufferedWriter中。 Flush将这些字节发送到包装的FileWriter。如果你收集到足够的字节,它将刷新到目标文件,但你可能会失去你的某些进程崩溃或磁盘问题的信息。
如果我在flush()中调用writter.flush(),则会重复日志。虽然这可能发生了什么?
也许您已将此处理程序的两个实例添加到记录器,并且两者都附加到同一文件。 Logger.addHandler的工作方式与List
类似,而不像Set
。将代码添加到Print the logger tree,它将告诉您安装了多少个处理程序实例。
只有当Java virtual machine shuts down和处理程序在LogManager中可见时,才会隐式调用我确定没有进程崩溃或磁盘问题,我相信close close会刷新。然而,我不知道为什么没有记录任何内容 - 而且只有文件尚未创建。
Close。如果文档中描述的关闭不干净,则不会刷新缓冲的写入程序的内容。
答案 1 :(得分:0)
好的,经过两天的战斗,我开始意识到进程正在一个守护进程上运行,因此,处理程序的close()
仅在守护程序被杀死时被调用。我相信这几乎同时导致多次调用flush()
。没有守护进程运行进程解决了这个问题。