Служба наблюдения Java NIO создала и ENTRY_CREATE, и ENTRY_MODIFY, когда новый файл добавляется в папку наблюдения

Я вижу странное поведение (не уверен, что это ожидаемое поведение) при использовании java.nio.file.WatchService.

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

"ENTRY_CREATE" и "ENTRY_MODIFY".

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

Кто-нибудь может объяснить, почему создается дополнительное событие ENTRY_MODIFY?

Мой код:

public void watch() {
    WatchKey key = watcher.poll();

    //log.info("Watcher scheduler running. Watch key {}", key.hashCode());

    if (key != null) {
        Workflow workflow = keys.get(key);
        log.info("Runing watcher for key '{}'  and workflow {}", key.hashCode(), workflow.getName());
        File hotFolder = new File(workflow.getFolderPath());
        Path dir = hotFolder.toPath();

        for (WatchEvent<?> event : key.pollEvents()) {
            WatchEvent<Path> ev = cast(event);
            Path name = ev.context();
            Path child = dir.resolve(name);

            log.info("Polling event for name {} and child {} and dir {}", name.toFile(), child.toFile(), dir.toFile());

            if (Files.isDirectory(child, LinkOption.NOFOLLOW_LINKS))
                continue;

            try {
                switch (event.kind().name()) {
                case "ENTRY_CREATE":
                    log.info("New file {}", child.toFile());
                    fileService.processNewFile(child.toFile(), workflow);
                    break;
                case "ENTRY_MODIFY":
                    log.info("File modified.... {}", child.toFile());
                    fileService.processModifiedFile(child.toFile(),
                            workflow);
                    break;
                default:
                    log.error("Unknown event {} for file {}", event.kind()
                            .name(), child.toFile());
                    break;
                }
                // Operation op = Operation.from(event.kind());
                // if (op != null)
                // publisher.publishEvent(new FileEvent(child.toFile(),
                // workflow, op));
            } catch (Throwable t) {
                log.warn("Error while procesing file event", t);
            }
        }

        key.reset();
    }
}

Поэтому, когда я копирую файл, скажем, name = "abc.txt", отображаются журналы:
Новый файл abc.txt
Файл изменен.... abc.txt


Любые входные данные очень востребованы.

2 ответа

Проверьте раздел "Зависимости платформы" в JavaDoc WatchService.

Наблюдатель ведет себя правильно в описанной вами ситуации. И, строго говоря, когда вы копируете файл в папку, файлы действительно создаются, а затем изменяются.

При использовании WatcherService нужно учитывать много вещей, их поведение сильно варьируется, например:

  • Операционные системы
  • Зашифрованные диски
  • Сетевые акции
  • ...

Я думаю, что вопрос уже был дан ответ здесь.

Например, Java: WatchService получает информацию перед копированием контента.

В двух словах, события генерируются вашей операционной системой. У вас есть два события, что означает, что ваша ОС выполняет копирование неатомарным способом. Если вы попытаетесь прочитать файл где-то между ENTRY_CREATE и ENTRY_MODIFY, это будет противоречиво. Но опять же, это зависит от вашей ОС. Например, в Windows 7 я получаю ENTRY_CREATE один раз и ENTRY_MODIFY два раза для больших файлов. Таким образом, вы на самом деле не можете быть уверены в том, что файл успешно скопирован или нет, вам нужно придумать метрики, зависящие от приложения / ОС.

Другие вопросы по тегам