WatchService / WatchEvent / Путь от события - PullRequest
4 голосов
/ 21 ноября 2011

Я рекурсивно просматриваю каталог (и, следовательно, все его подкаталоги и файлы) на предмет изменений.

Кажется, если я создаю или удаляю каталог или файл в подкаталоге корневого каталога длясмотреть, что у Path, который включен в экземпляр WatchEvent, который каждый получает (через context ()), нет родителя, и поэтому rootDirToWatch.resolve(event.context()) не возвращает путь, который мне нравится иметь.

Например:

* Наблюдается 1008 *, затем я создаю новый каталог в /home/johannes/test/foo/bar с именем baz, я получаю новый экземпляр Path, который /home/johannes/test/baz вместо /home/johannes/test/foo/bar/baz

Любые предложениячто не так?

Я просто использую посетителя для просмотра всех подкаталогов в определенном корневом каталоге (просмотр всего каталога со всеми его потомками):

@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 возвращает относительный путь, понятно, почему он ведет себя так, как описано, но я не хочу еще раз проходить по каталогу, чтобы найти путь от корневого каталога для просмотра к добавленному / удаленному / измененному файлу где-то выше в иерархии.

Редактировать: Я нашел решение («индексация» ключей): http://docs.oracle.com/javase/tutorial/displayCode.html?code=http://docs.oracle.com/javase/tutorial/essential/io/examples/WatchDir.java

Ответы [ 2 ]

2 голосов
/ 13 ноября 2013

Алан прав.

Вы должны использовать Watchable в ключе.

Вот код Scala из моего приложения.Я думаю, вы сможете прочитать его.

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)
  }
}

Это работает нормально, но позаботьтесь о некоторых угловых случаях:

/**
 * 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();

Извините, я не знаю, как поступитьс этим.

1 голос
/ 21 ноября 2011

Метод watchable () вернет исходный Watchable, чтобы вы могли использовать его в качестве родительского каталога.

...