我可以使用 WatchService(而不是整个目录)监视单个文件更改吗?
2022-08-31 12:12:47
当我尝试注册文件而不是目录时,会抛出。我可以侦听单个文件更改,而不是整个目录吗?java.nio.file.NotDirectoryException
当我尝试注册文件而不是目录时,会抛出。我可以侦听单个文件更改,而不是整个目录吗?java.nio.file.NotDirectoryException
只需在目录中筛选所需文件的事件:
final Path path = FileSystems.getDefault().getPath(System.getProperty("user.home"), "Desktop");
System.out.println(path);
try (final WatchService watchService = FileSystems.getDefault().newWatchService()) {
final WatchKey watchKey = path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY);
while (true) {
final WatchKey wk = watchService.take();
for (WatchEvent<?> event : wk.pollEvents()) {
//we only register "ENTRY_MODIFY" so the context is always a Path.
final Path changed = (Path) event.context();
System.out.println(changed);
if (changed.endsWith("myFile.txt")) {
System.out.println("My file has changed");
}
}
// reset the key
boolean valid = wk.reset();
if (!valid) {
System.out.println("Key has been unregisterede");
}
}
}
在这里,我们检查更改的文件是否是“myFile.txt”,如果是,则执行任何操作。
其他答案是正确的,您必须监视目录并筛选您的特定文件。但是,您可能希望线程在后台运行。接受的答案可以无限期地阻塞,并且不会关闭监视服务。适用于单独线程的解决方案可能如下所示:watchService.take();
public class FileWatcher extends Thread {
private final File file;
private AtomicBoolean stop = new AtomicBoolean(false);
public FileWatcher(File file) {
this.file = file;
}
public boolean isStopped() { return stop.get(); }
public void stopThread() { stop.set(true); }
public void doOnChange() {
// Do whatever action you want here
}
@Override
public void run() {
try (WatchService watcher = FileSystems.getDefault().newWatchService()) {
Path path = file.toPath().getParent();
path.register(watcher, StandardWatchEventKinds.ENTRY_MODIFY);
while (!isStopped()) {
WatchKey key;
try { key = watcher.poll(25, TimeUnit.MILLISECONDS); }
catch (InterruptedException e) { return; }
if (key == null) { Thread.yield(); continue; }
for (WatchEvent<?> event : key.pollEvents()) {
WatchEvent.Kind<?> kind = event.kind();
@SuppressWarnings("unchecked")
WatchEvent<Path> ev = (WatchEvent<Path>) event;
Path filename = ev.context();
if (kind == StandardWatchEventKinds.OVERFLOW) {
Thread.yield();
continue;
} else if (kind == java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY
&& filename.toString().equals(file.getName())) {
doOnChange();
}
boolean valid = key.reset();
if (!valid) { break; }
}
Thread.yield();
}
} catch (Throwable e) {
// Log or rethrow the error
}
}
}
我尝试从接受的答案和本文开始工作。您应该能够将此线程与该线程一起使用,并通过调用该线程来停止它。new FileWatcher(new File("/home/me/myfile")).start()
stopThread()