问题描述
我正在尝试使用 java.logging.util 在文件上打印日志信息。此解决方案有效,但日志中的信息未随回车一起显示。 我的代码:
主要
String url ="opc.tcp://DEV85:53530/OPcua/SimulationServer";
MyFormatter formatter=new MyFormatter();
fh = new FileHandler("C:/tmp/MyLogFile.log",true);
logger.addHandler(fh);
fh.setFormatter(formatter);
doSomething else()
EndpointDescription[] endpoints = myClient.discoverEndpoints(url);
for(EndpointDescription e: endpoints) {
//System.out.println(e);
logger.info(e.toString());
}
格式化程序类
public class MyFormatter extends Formatter {
// Create a DateFormat to format the logger timestamp.
private static final DateFormat df = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss.SSS");
@Override
public String format(LogRecord record) {
StringBuilder builder = new StringBuilder(1000);
builder.append(df.format(new Date(record.getMillis()))).append(" - ");
builder.append("[").append(record.getSourceClassName()).append(".");
builder.append(record.getSourceMethodName()).append("] - ");
builder.append("[").append(record.getLevel()).append("] - ");
builder.append(formatMessage(record));
builder.append(System.getProperty("line.separator","\r\n"));
//builder.append("\n");
return builder.toString();
}
}
输出就在一行上。我在网上找到了一些解决方案,但对我不起作用。
解决方法
简单地说,SimpleDateFormat 不是线程安全的,因此您不需要将其存储为对象或静态引用。每次调用或使用 java.time.format 包创建一个新实例。修复此问题,使其不会导致任何幻影问题。
此解决方案有效,但日志中的信息未随回车一起显示。
使用可以显示空白字符的文本编辑器打开文件。您的格式化程序代码看起来正确。您需要仔细检查您使用的查看器是否只是错误地呈现文本(记事本)。最坏的情况是使用 FileInputStream 并将原始字节读取为十六进制。应该能够看到 line separator 的十六进制值。您对格式化程序本身的单元测试应该能够验证行分隔符是否存在。
另一个问题是您必须证明您的格式化程序正在被使用。您正在打开文件进行追加,因此其他格式化程序可以将其数据插入同一文件中。考虑覆盖 getHead 和 getTail 以生成唯一 ID 并将其放入格式化程序中进行测试。这将显示格式化程序的开始和停止。
java.util.logging.SimpleFormatter 也可以支持这种格式,但它是一个全局设置,不能为每个对象自定义。