【问题标题】:WatchService (Windows 7): when deleting a file, it fires both ENTRY_MODIFY and ENTRY_DELETE events?WatchService (Windows 7):删除文件时,它会触发 ENTRY_MODIFY 和 ENTRY_DELETE 事件吗?
【发布时间】:2015-01-28 19:59:50
【问题描述】:

在使用 WatchService 时,我发现如果我删除正在监视的目录中的文件,它会触发 ENTRY_MODIFY,然后是 ENTRY_DELETE 事件。

我意识到从技术上讲,文件可能会在删除之前被修改,但删除文件会触发 ENTRY_MODIFY(大概没人关心)真的是预期的行为吗?

为了处理这个问题,我必须在触发传递 ENTRY_MODIFY 事件之前添加一个条件来检查:

            if (eventKind == ENTRY_CREATE) {
                listener.fileCreated(file);
            } else if (eventKind == ENTRY_MODIFY) {
                if (Files.exists(fullPath, LinkOption.NOFOLLOW_LINKS)) {
                    listener.fileChanged(file);
                }
            } else if (eventKind == ENTRY_DELETE) {
                listener.fileDeleted(file);
            }

有没有更好的方法来处理这个问题(功能)?

【问题讨论】:

  • 我相信这是意料之中的,而您用来处理这种行为的单行代码对我来说似乎是一个简单的解决方案。
  • @colti:我还没有机会在 Linux 上进行测试。这里 Windows 和 Linux 的行为有什么不同吗?
  • 有可能,但我不确定。 Linux 实现使用 inotify,如果您想阅读:man7.org/linux/man-pages/man7/inotify.7.html
  • 在我的机器上 Files.exists() 在收到 ENTRY_MODIFY 事件后返回 true,除非等待大约 10 毫秒,这使得这非常不可靠。有没有更好的办法?
  • 我在 Windows 7 下运行,发现 WatchService 的行为在删除时一点也不可靠。有时我在删除文件时会收到 ENTRY_MODIFIED 和 ENTRY_DELETE。其他时候我只得到一个 ENTRY_MODIFIED。正如@Fulluphigh 提到的,检查文件是否存在也是不可靠的。我正在使用 Java 1.8 vm 运行,尽管为 1.7 编译。

标签: java watchservice


【解决方案1】:

我只能确认问题。根据 cmets 和我自己的观察,ENTRY_MODIFY 事件在文件被删除之前触发,您必须处理它。

假设我们有两个线程。一个在做Files.delete(),另一个在看目录并试图读取修改过的文件。以下任何一种情况都可能发生:

  1. Files.delete() 只是在观察线程接收到事件之前设法修改和删除文件。然后在ENTRY_MODIFY 之后检查文件是否存在的技术起作用了。
  2. Files.delete() 调用可能会失败(返回 false),因为该文件已被监视线程打开。

唯一的解决办法似乎是忽略观察线程中的所有IOExceptions,并重试Files.delete()调用几次。

我只尝试使用Files.delete() 从同一个 JVM 中删除文件。我没有尝试从系统上的其他进程中删除。问题在带有 NTFS 的 Windows 7~10 上重现,可能不会在其他操作系统上重现。

我鼓励其他人编辑此答案并添加他们的观察结果。

【讨论】:

    猜你喜欢
    • 2017-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-07
    • 2015-05-14
    • 1970-01-01
    • 2012-11-30
    • 1970-01-01
    相关资源
    最近更新 更多