【问题标题】:Java File/IO/NIO API for writing to files that can be read by other programs in real timeJava File/IO/NIO API,用于写入其他程序可以实时读取的文件
【发布时间】:2015-04-20 20:40:53
【问题描述】:

我正在使用一个 Java 控制台应用程序,该应用程序必须写入(附加)到两个单独的文件,对应于 OUTERR 流。 tailgrep 等外部实用程序将实时监控这些文件。我开始通过Appendable 接口写入这两个流,但在应用程序完成执行之前,文件似乎不会反映任何更改,在输出流上刷新和关闭之后。

服务

package com.mycompany;

public class Service {

                private Appendable outlog;
                private Appendable errlog;

                public Service(Appendable outlog, Appendable errlog) {
                        this.outlog = outlog;
                        this.errlog = errlog;
                }

                public void executeTask() throws Exception {

                                outlog.append("task execution started\n");
                                Thread.sleep(30 * 1000);
                                outlog.append("task execution completed\n");
                }
}

应用程序

package com.mycompany;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.PrintWriter;

public class Application {

        public static void main(String[] args) throws Exception {

                PrintWriter outlog = new PrintWriter(new BufferedWriter(new FileWriter("application.log")));
                PrintWriter errlog = new PrintWriter(new BufferedWriter(new FileWriter("application-err.log")));

                Service service = new Service(outlog, errlog);
                service.executeTask();

                outlog.flush();
                outlog.close();
                errlog.flush();
                errlog.close();
        }
}

我的设计从根本上是错误的,还是我应该以更好、更有效的方式来做这件事?

【问题讨论】:

  • 您是否尝试过使用日志库:slf4j、logback、log4j?
  • 应用程序可以控制这些 log 文件的名称,因此日志库在这种情况下不会很有帮助。将根据执行时间和用户身份生成多个文件。
  • 你试过不关闭就冲洗吗?例如,每次写入日志后刷新?
  • 调用flush() 确实应该可以将输出刷新到磁盘。这有可能在Windows上吗?还是将日志文件写入 NFS 等网络文件系统,而阅读器位于另一台主机上?您发布的代码实际上并未编译,我怀疑它是伪代码。您能否编辑您的问题以包含一个实际工作的示例程序?
  • 如果您获得 FileDescriptor 并在每次写入后调用 sync() 方法,然后刷新,文件内容将对其他进程可见。您不必关闭该文件。

标签: java logging file-io nio tail


【解决方案1】:

Service 类中,将outlogerrlog 字段声明并传播为Writer(实现Appendable)并在附加消息后调用outlog.flush()

public class Service {

  private Writer outlog;
  private Writer errlog;

  public Service(Writer outlog, Writer errlog) {
    this.outlog = outlog;
    this.errlog = errlog;
  }

  public void executeTask() throws Exception {
    try {
      outlog.append("task execution started\n");
      outlog.append("task execution completed\n");
    finally {
      outlog.flush();
    }
  }
}

【讨论】:

  • 是否值得通过子类化 PrintWriter 来覆盖 .append() 方法?这样,我可以在 service 不知道的覆盖方法中放置一个 .flush()
猜你喜欢
  • 2021-04-06
  • 2019-10-20
  • 2020-07-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多