当我试图注册一个文件而不是一个目录java时。尼奥。文件引发NotDirectoryException
。我可以监听单个文件的更改,而不是整个目录吗?
不,不可能注册文件,监视服务不这样工作。但是注册目录实际上会监视目录子目录(文件和子目录)上的更改,而不是目录本身的更改。
如果你想观看一个文件,那么你可以向观看服务注册包含该文件的目录。路径register()文档说明:
监视键java。尼奥。文件路径寄存器(WatchService watcher、Kind[]事件、修饰符…修饰符)引发IOException
向监视服务注册此路径下的文件。
在这个版本中,这个路径定位一个存在的目录。该目录在watch服务中注册,以便可以监视目录中的条目
然后,您需要处理条目上的事件,并通过检查事件的上下文值来检测与您感兴趣的文件相关的事件。上下文值表示条目的名称(实际上是相对于其父项路径的条目路径,它正是子项名称)。这里有一个例子。
其他答案是正确的,您必须查看目录并筛选特定文件。但是,您可能希望在后台运行线程。接受的答案可以无限期地阻止watchService。拿()
并且不关闭WatchService。适用于单独线程的解决方案可能如下所示:
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
}
}
}
我试着从公认的答案和这篇文章开始工作。您应该能够将此线程与新的FileWatcher(新文件(“/home/me/myfile”))一起使用。启动()
并通过调用线程上的stopThread()
停止它。
只需在目录中筛选所需文件的事件:
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”,如果是则执行任何操作。
问题内容: 如何在Linux( ext3 文件系统)中监视 整个目录树 的更改? __ 当前,该目录包含大约 3,000个子目录* 中的大约 一百万个文件 ,这些 文件 分为三个目录级别。 * 这些文件大多是小文件(<1kb,有些则最大100 kb)。这是一种队列,我需要知道在发生这种情况的5-10秒内何时创建,删除文件或修改其内容。 我知道这里有 inotify 和sorting,但是AFAIK
问题内容: 这就是问题所在:我们想要一个哈希表,其条目是线程安全的。 假设我的哈希表为,并且我想安全地增加条目线程之一的值:可以吗? 然后,每当我想增加一个条目时: 我认为它比ConcurrentHashMap更好,因为它仅锁定一个条目,而不像ConcurrentHashMap使用存储桶并将一组条目锁定在一起。 更重要的是,我不知道如何安全地使用COncurrenHashMap对其进行递增。例如,
问题内容: 是否可以“监视”指令上的ui更改?像这样的东西: 问题答案: 是。您可以使用,如果你在属性利用插值。 但是,如果这不是一个插值属性,并且您希望它可以从应用程序中的其他位置更改(绝对不建议这样做,请阅读Common Pitfalls ),那么函数可以返回: 无论如何,对您来说最好的方法可能是更改更改元素类的代码。它何时更改?
问题内容: 我有我的mysql数据库的mysqldump备份,该数据库由我们的所有表组成,大约440兆。我想从mysqldump恢复仅其中一张表的内容。这可能吗?从理论上讲,我可以剪掉重建所需表的部分,但我什至不知道如何有效地编辑该大小的文本文档。 问题答案: 您可以尝试使用sed以便仅提取所需的表。 假设表的名称为,文件mysql.dump是包含您的大型转储的文件: 这将在文件中复制位于与下一个
问题内容: 就像一个类似的SO问题一样,我正在尝试监视Linux机器上的目录以添加新文件,并希望在这些新文件到达时立即对其进行处理。关于实现此最佳方法的任何想法? 问题答案: 看inotify。 使用inotify,您可以监视用于文件创建的目录。
问题内容: 我在这里写的主要是关于从哪里开始的建议。我已经实现了一个类,该类将使用Java的WatchService递归监视目录。它可以很好地检测更改,但是我注意到了一个致命的缺陷:我无法删除包含正在监视的目录的正在监视的目录。这似乎是WatchService的限制。 我还稍微研究了Apache的VFS FileListener,但是在花了大约6个小时的时间来围绕它构建某种包装之前,我想也许我只是