java - 观看目录时仅触发一次事件

标签 java nio

使用 java.nio 监视服务,我尝试监视一个目录及其所有子目录:

Files.walkFileTree(projectPath, new SimpleFileVisitor<Path>() {
   @Override
   public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
        WatchKey key = dir.register(watcher, StandardWatchEventKinds.ENTRY_CREATE,
                StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE);
        watched.put(key, new WatchableDirectory(dir, projectPath));
        return FileVisitResult.CONTINUE;
    }
});

然后我等待事件:

executor.submit(new Runnable() {
        @Override
        public void run() {
            try {
                WatchKey key;
                while ((key = watcher.take()) != null) {
                    List<WatchEvent<?>> events = key.pollEvents();
                    WatchableDirectory watchableDirectory = watched.get(key);
                    for (WatchEvent<?> event : events) {
                         ....
                    }
             }
          ....
         }
    }

(watched 是一个 Map,保存从键到目录元数据的映射)

但是,只会触发给定目录的第一个事件。每当我更改目录中的另一个文件时,其中一个文件已经更改,什么也不会发生(我通过放置断点和期望 for 循环中的逻辑发生来验证这一点)。

但是,如果我修改另一个目录中的文件,则一切正常(同样,只有第一次)。

没有抛出异常(java.lang.Exception 有一个 catch 子句),显然循环继续运行。

我认为可能一旦消费,该目录可能会被注销。因此,我添加了一行以在处理其文件后重新注册它。没有影响。

Windows 7、Java 7。

有什么想法吗?

最佳答案

别忘了打电话

key.reset();

while 循环中使用完它之后。

docs状态

Otherwise if there are pending events for the object then this watch key is immediately re-queued to the watch service. If there are no pending events then the watch key is put into the ready state and will remain in that state until an event is detected or the watch key is cancelled.

Watch keys are safe for use by multiple concurrent threads. Where there are several threads retrieving signalled keys from a watch service then care should be taken to ensure that the reset method is only invoked after the events for the object have been processed. This ensures that one thread is processing the events for an object at any time.

因此,如果您不重置,就好像您的 watch 被禁用了一样。

WatchKey#reset() 返回一个 boolean 值,判断它是否有效。按照 tutorial 中的说明处理该案例.

Marko强调:

After the events for the key have been processed, you need to put the key back into a ready state by invoking reset. If this method returns false, the key is no longer valid and the loop can exit. This step is very important. If you fail to invoke reset, this key will not receive any further events.

关于java - 观看目录时仅触发一次事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20180547/

相关文章:

java - 读取格式错误的文件时 StreamDecoder 与 InputStreamReader

java - GWT 滚动处理程序

Java forEach 无法使用 IntStream.range 在 flatMap 上工作

java - 是否有允许动态增长并扩展 java.nio.ByteBuffer 的 ByteBuffer 实现?

java - 如何使用 AsynchronousFileChannel 有效地读取到 StringBuffer

java - 避免额外的换行,写入 .txt 文件

java - 如何在 whatsapp 和 facebook 分享 libgdx 游戏得分的截图?

java - 无法将 Theme.Holo 用于我的第一个 Android 应用程序的样式

java - 属性未传递给 bean

java - 如何获取 Windows 负载值