问题描述
我正在递归地查看目录(以及所有子目录和文件)的更改.
I'm recursively watching a directory (and therefore all subdirs and files) for changes.
似乎,如果我要在根目录的子目录中创建或删除目录或文件以监视包含在WatchEvent实例中的路径(通过context()接收)没有父级,因此rootDirToWatch.resolve(event.context())
没有返回我想要的路径.
It seems, if I'm creating or deleting a directory or file in a subdirectory of the root-dir to watch the Path which is included in the WatchEvent instance one receives (via context()) has no Parent and therefore rootDirToWatch.resolve(event.context())
is not returning the Path I like to have.
例如:
/home/johannes/test
,然后在/home/johannes/test/foo/bar
中创建一个名为baz
的新目录,得到一个新的Path实例,该实例是/home/johannes/test/baz
代替/home/johannes/test/foo/bar/baz
/home/johannes/test
is watched, then I'm creating a new directory in /home/johannes/test/foo/bar
named baz
, I'm getting a new Path instance which is/home/johannes/test/baz
instead of /home/johannes/test/foo/bar/baz
任何建议出什么事了吗?
Any suggestions what's going wrong?
我只是使用访问者来监视某个根目录中要监视的所有子目录(监视整个目录及其后代):
I'm simply using a visitor to watch for all subdirectories in a certain root-directory to watch (watching a whole directory with all it's descendants):
@Override
public FileVisitResult preVisitDirectory(final Path pDir, final BasicFileAttributes pAttrs)
throws IOException
{
checkNotNull(pDir);
checkNotNull(pAttrs);
pDir.register(mWatcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
return FileVisitResult.CONTINUE;
}
我认为我真的必须使用访问者或至少在观察者中注册所有子目录.当WatchEvent返回一个相对路径时,很清楚为什么它会如此描述,但是我不想再次遍历该目录以查找从要监视的根目录到层次结构中更深一层的添加/删除/修改的文件的路径.
I think I really have to use a visitor or at least register all subdirs with the watcher. As WatchEvent returns a relative path it's clear why it behaves as described, but I don't want to traverse the directory once more to find the path from the root-dir to watch to the added/deleted/modified File somewhere depper in the hierarchy.
我已经找到了解决方案(对索引进行索引"): http://docs.oracle.com/javase/tutorial/displayCode.html?code=http://docs. oracle.com/javase/tutorial/essential/io/examples/WatchDir.java
I've found the solution ("indexing" the keys): http://docs.oracle.com/javase/tutorial/displayCode.html?code=http://docs.oracle.com/javase/tutorial/essential/io/examples/WatchDir.java
推荐答案
艾伦是正确的.
您应该在按键中使用Watchable.
You should use the Watchable in the key.
这是我应用中的Scala代码.我想您将能够阅读它.
Here's a Scala code from my app. I guess you will be able to read it.
object FsNotifType extends Enumeration {
val Create, Update, Delete = Value
}
case class FsNotif(notifType: FsNotifType.Value,path: Path)
object FsNotif {
def apply(watchKey: WatchKey,event: java.nio.file.WatchEvent[_]): FsNotif = {
val fsNotifType = event.kind() match {
case StandardWatchEventKinds.ENTRY_CREATE => FsNotifType.Create
case StandardWatchEventKinds.ENTRY_MODIFY => FsNotifType.Update
case StandardWatchEventKinds.ENTRY_DELETE => FsNotifType.Delete
case _ => throw new IllegalStateException("Unknown FS event kind: " + event)
}
val watchedPath = watchKey.watchable().asInstanceOf[Path]
val relativePath = event.context().asInstanceOf[Path]
val absolutePath = watchedPath.resolve(relativePath)
FsNotif(fsNotifType,absolutePath)
}
}
这可以正常工作,但要注意一些极端的情况:
This works fine, but take care of some corner cases:
/**
* Returns the object for which this watch key was created. This method will
* continue to return the object even after the key is cancelled.
*
* <p> As the {@code WatchService} is intended to map directly on to the
* native file event notification facility (where available) then many of
* details on how registered objects are watched is highly implementation
* specific. When watching a directory for changes for example, and the
* directory is moved or renamed in the file system, there is no guarantee
* that the watch key will be cancelled and so the object returned by this
* method may no longer be a valid path to the directory.
*
* @return the object for which this watch key was created
*/
Watchable watchable();
对不起,我不知道该如何处理.
Sorry, I don't know how to deal with this.
这篇关于WatchService/WatchEvent/事件的路径的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!