WatchService / WatchEvent / Path from event

I recursively scan the directory (and therefore all sub-folders and files) for changes.

It seems if I create or delete a directory or file in a subdirectory of the root directory to see the Path that is included in the WatchEvent instance that you receive (via context ()) does not have a parent, and therefore rootDirToWatch.resolve(event.context()) doesn't return the path that I like.

For instance:

/home/johannes/test , then I create a new directory in /home/johannes/test/foo/bar named baz , I get a new Path instance that is /home/johannes/test/baz instead of /home/johannes/test/foo/bar/baz

Any suggestions what goes wrong?

I just use the visitor to watch all the subdirectories in a specific root directory to watch (by looking at the whole folder with all its 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; } 

Edit: I think I really need to use a visitor, or at least register all the sub-racers with an observer. Since WatchEvent returns a relative path, it clearly explains why it behaves as described, but I don’t want to navigate the directory again to find the path from the -dir root to look at the added / deleted / modified file somewhere below in hierarchy.

Edit: I found a solution ("indexing" the keys): http://docs.oracle.com/javase/tutorial/displayCode.html?code=http://docs.oracle.com/javase/tutorial/essential/io/ examples / WatchDir.java

+4
source share
2 answers

Alan is right.

You must use Watchable in a key.

Here is the Scala code from my application. I think you can 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 great, but take care of some 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 handle this.

+2
source

The watchable () method returns the original Watchable, so you can use it as the parent directory.

+1
source

Source: https://habr.com/ru/post/1382197/


All Articles