其他人的过程是通过在事件发生时一次添加一行来创建CSV文件.我无法控制文件格式或其他进程,但我知道它只会附加.
在Java程序中,我想监视这个文件,当附加一行时,读取新行并根据内容做出反应.暂时忽略CSV解析问题.监视文件以进行更改并一次读取一行的最佳方法是什么?
理想情况下,这将使用标准库类.该文件可能在网络驱动器上,所以我想要一些强大的失败.如果可能的话,我宁愿不使用轮询 - 我更喜欢某种阻塞解决方案.
编辑 - 鉴于标准类无法实现阻塞解决方案(感谢您的回答),最强大的轮询解决方案是什么?我不想每次都重新读取整个文件,因为它可能会变得非常大.
从Java 7开始,FileSystem类上就有了newWatchService()方法.
但是,有一些警告:
在Java 7之前,标准API无法实现.
我尝试了以下(以1秒的间隔轮询)并且它可以工作(只是在处理中打印):
private static void monitorFile(File file) throws IOException {
final int POLL_INTERVAL = 1000;
FileReader reader = new FileReader(file);
BufferedReader buffered = new BufferedReader(reader);
try {
while(true) {
String line = buffered.readLine();
if(line == null) {
// end of file, start polling
Thread.sleep(POLL_INTERVAL);
} else {
System.out.println(line);
}
}
} catch(InterruptedException ex) {
ex.printStackTrace();
}
}
Run Code Online (Sandbox Code Playgroud)
由于没有其他人建议使用当前生产Java的解决方案我以为我会添加它.如果有缺陷请添加评论.
如果使用WatchService类对文件进行任何更改,您可以注册以获得文件系统的通知.这需要Java7,这里是文档的链接 http://docs.oracle.com/javase/tutorial/essential/io/notification.html
这里是用于执行此操作的代码段:
public FileWatcher(Path dir) {
this.watcher = FileSystems.getDefault().newWatchService();
WatchKey key = dir.register(watcher, ENTRY_MODIFY);
}
void processEvents() {
for (;;) {
// wait for key to be signalled
WatchKey key;
try {
key = watcher.take();
} catch (InterruptedException x) {
return;
}
for (WatchEvent<?> event : key.pollEvents()) {
WatchEvent.Kind<?> kind = event.kind();
if (kind == OVERFLOW) {
continue;
}
// Context for directory entry event is the file name of entry
WatchEvent<Path> ev = cast(event);
Path name = ev.context();
Path child = dir.resolve(name);
// print out event
System.out.format("%s: %s file \n", event.kind().name(), child);
}
// reset key and remove from set if directory no longer accessible
boolean valid = key.reset();
}
}
Run Code Online (Sandbox Code Playgroud)