Java7的WatchService - 如何检测实际监视目录的重命名/移动

11
我正在使用WatchService来同步数据文件和应用程序工作台。当我重命名/移动被监视的目录时,我没有收到任何事件,也没有WatchKey变得无效。我仍然可以从重命名后的目录中获取事件,但据我所知,除了WatchKey.watchable()之外,找不到WatchKey的实际路径,但这仍然返回原始目录路径。我想避免对被观察目录进行锁定以防止更改,因为我希望尽可能保持应用程序的轻量化。

我在Windows 7上使用JDK 7u10时遇到了这个问题

你知道有没有任何解决此问题的方法,而不需要锁定目录或监视所有目录到根目录?

更新

在Linux上,我观察到了相同的行为。

到目前为止,现在似乎有三个选项。

1)依赖用户的纪律性,他/她不会移动数据目录。我不太喜欢这个选项,因为它可能会导致未定义的行为。

2)使用更广泛的非标准本地库

3)创建监视器层次结构位于上级目录中。这些将仅接受ENTRY_DELETE事件,因为此事件(或OVERFLOW)必须出现在实际观察的目录被移动或删除并因此无效的时刻。


Javadoc指定使用本机可用的机制进行操作,您尝试并搜索了Win7在这种情况下的机制吗? - fge
Windows上的本地机制使用目录句柄,当目录被重命名/移动时不会改变,但会发送特定事件。这本来不是问题,但在Java中我没有看到任何检测这些Windows特定事件的方法,也没有任何获取和检查实际目录句柄值的方法。 - rjezek
1个回答

6
我的理解是重命名目录会在旧和新父目录上产生文件系统事件,而不是在被重命名的目录上。根据Can iNotify tell me where a monitored file is moved?的答案,操作系统无法告诉您移动到哪里,除非您正在监视目标目录。(而且,在Java 7/8中,MOVE事件不受监视服务实现处理。)
更新
您可以尝试使用jpathwatch项目,该项目使用标准Java7 WatchService API添加了对( 平台特定) 扩展事件的支持。
参考资料:
文档 - http://jpathwatch.wordpress.com/ javadoc - http://jpathwatch.sourceforge.net/

其实我并不需要知道我的目录被移动到哪里。只要知道它被移动了,这样我就可以根据新的情况更改WatchKey注册。我已经检查了JRE实现,似乎他们只是从系统中丢弃了这些事件。到目前为止,处理当前实现的唯一方法似乎是监视所有目录直到根目录。这看起来不太好,但我认为我可以通过这种方式解决它,或者你有更好的想法吗? - rjezek
根据jpathwatch库中的KEY_INVALID,似乎这是一个孤立的Windows问题,因为其他系统在它移动时会使WatchKey无效。事实上,问题是标准Java 7 WatchService是否也会像这样运作,因此我将进一步研究其在Linux上的行为,并在此处公布我的结果。 - rjezek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接