Подтвердить что ты не робот

Событие запускается только один раз при просмотре каталога

Используя службу просмотра java.nio, я пытаюсь посмотреть каталог и все его подкаталоги:

Files.walkFileTree(projectPath, new SimpleFileVisitor<Path>() {
   @Override
   public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
        WatchKey key = dir.register(watcher, StandardWatchEventKinds.ENTRY_CREATE,
                StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE);
        watched.put(key, new WatchableDirectory(dir, projectPath));
        return FileVisitResult.CONTINUE;
    }
});

Затем я жду событий:

executor.submit(new Runnable() {
        @Override
        public void run() {
            try {
                WatchKey key;
                while ((key = watcher.take()) != null) {
                    List<WatchEvent<?>> events = key.pollEvents();
                    WatchableDirectory watchableDirectory = watched.get(key);
                    for (WatchEvent<?> event : events) {
                         ....
                    }
             }
          ....
         }
    }

(watched - это Map, который содержит сопоставления от ключа к метаданным о каталоге)

Однако только первое событие для данного каталога запускается. Всякий раз, когда я меняю другой файл в каталоге, в котором файл уже был изменен, ничего не происходит (я проверяю, что, поставив точку останова и ожидая, что логика в for-loop будет иметь место).

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

Никаких исключений не выбрасывается (есть предложение catch для java.lang.Exception), и цикл, очевидно, продолжает работать.

Я подумал, что, возможно, однажды его уничтожил, каталог может быть отменен. Поэтому я добавил строку, чтобы перерегистрировать ее после обработки файла. Без эффекта.

Windows 7, Java 7.

Любые идеи, почему?

4b9b3361

Ответ 1

Не забудьте вызвать

key.reset();

после того, как вы закончите использовать его в цикле while.

docs состояние

В противном случае, если есть ожидающие события для объекта, тогда эти часы ключ немедленно переключается на службу просмотра. Если нет ожидающие события, тогда ключ часов будет переведен в состояние готовности и будет остаются в этом состоянии до тех пор, пока не будет обнаружено событие или ключ часов отменен.

и

Клавиши наблюдения безопасны для использования несколькими параллельными потоками. где есть несколько потоков, получающих сигнальные ключи от часов следует соблюдать осторожность, чтобы гарантировать, что метод resetвызывается только после обработки событий для объекта. Эта гарантирует, что один поток обрабатывает события для объекта в любом время.

Итак, если вы не reset, это значит, что ваши часы отключены.

WatchKey#reset() возвращает логическое значение, если оно действительно или нет. Обращайтесь к этому случаю, как описано в tutorial.

Marko подчеркивает:

После того, как события для ключа были обработаны, вам необходимо войдите в состояние готовности, вызвав reset. Если этот метод вернется false, ключ больше не действует, и цикл может выйти. Этот шаг очень важно. Если вы не вызываете reset, этот ключ не будет получать любые дальнейшие события.