我想从java应用程序中"尾部-f"很多日志文件。
我通过监控大小和上次更新并反复打开文件并在文件大小或上次更新时间更改时读取最后几个字节来使其工作 - 然后立即关闭它。
这似乎有问题,因为当记录器决定重命名会导致某种问题的文件时,我可能会打开它。
我还想检测一个"滚动"文件,其机制比注意到文件大小减小更确定......似乎容易出错,但不太可能。
由于我似乎无法访问文件描述符或其他低级文件实用程序,我可能无法重现 tail 的行为 - 但是有什么技巧可以在不"锁定"文件以进行重命名/删除的情况下读取文件(Windows 7)
我想另一种可能性是实际生成一个 tail -f 进程并读取进程输出,但这似乎有点沉重——我在这里扫描了 60 个日志文件,其中一些有很多输出(大多数将是空闲的)。
Apache Commons 有一个 Tailer 类,它会做你想要的吗?如果是这样,它具有滚动检测机制以及阅读内容,因此您将获得所需的一切。
如果这做不到,可能是没有办法用纯java做到这一点。例如,您需要一些帮助,C代码,使用fopen SH_DENYNO参数允许在Windows上共享打开。或者,然后通过执行系统命令来调用尾部实现。
但是,由于打开日志文件的代码是导致锁定它的代码,因此即使这样也可能无济于事。在这种情况下,唯一真正的选择是更改日志记录的工作方式,因为这是锁定文件的罪魁祸首。Log4j可以使用SocketAppender等。
使用 apache.commons.io
这里有一个简单的例子
public class LogTailTest {
/**
* TailerListener implementation.
*/
static public class ShowLinesListener extends TailerListenerAdapter {
@Override
public void handle(String line) {
System.out.println(line);
}
}
public static void main(String args[]) {
TailerListener listener = new ShowLinesListener();
File file = new File("./test.log");
Tailer tailer = new Tailer(file, listener, 1000);
tailer.run();
try {
Thread.sleep(100000);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
tailer.stop();
}
}
在 Linux 中,您不会有问题,因为锁定仅advisory
.但在Windows
,情况有所不同。
这应该取决于您的记录器(我假设 log4j)打开要记录的文件的模式。
查看此答案C#
似乎有一个参数dwShareMode
可用于这种共享。
我相信NIO
将是要走的路。查看dwShareMode
参数是否可作为NIO
API 的一部分使用