Java File/IO/NIO API,用于写入可由其他程序实时读取的文件

Java File/IO/NIO API,用于写入可由其他程序实时读取的文件,java,logging,file-io,nio,tail,Java,Logging,File Io,Nio,Tail,我正在使用一个Java控制台应用程序,该应用程序必须写入(追加)两个单独的文件,对应于OUT和ERR流。外部实用程序,如tail和grep将实时监控这些文件。我一开始是通过appendeable接口写入这两个流的,但是在应用程序完成执行之前,在刷新并关闭输出流之后,文件似乎不会反映任何更改 服务 package com.mycompany; public class Service { private Appendable outlog;

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

服务

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();
        }
}

我的设计从根本上是错误的,还是应该以更好、更有效的方式来实现这一点?

服务
类中,将
输出日志
错误日志
字段声明并传播为
编写器
(实现
可追加
)并调用
输出日志.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();
    }
  }
}

您是否尝试过使用日志库:slf4j、logback、log4j?应用程序可以控制这些日志文件的名称,因此日志库在这种情况下没有多大帮助。将根据执行时间和用户标识生成多个文件。您是否尝试过在不关闭的情况下刷新?例如,每次写入日志后刷新?调用
flush()
确实应该可以将输出刷新到磁盘。这有可能在Windows上吗?或者日志文件正在写入NFS这样的网络文件系统,而读卡器位于另一台主机上?您发布的代码实际上并没有编译,我怀疑它是伪代码。您是否可以编辑您的问题以包含实际的工作示例程序?如果您在每次写入后都获得FileDescriptor并调用sync()方法,然后刷新,则其他进程将可以看到文件内容。您不必关闭该文件。是否值得通过对PrintWriter进行子分类来重写
.append()
方法?这样,我就可以在
服务不知道的情况下,将
.flush()
放在重写的方法中。