当向监视文件夹添加新文件时,Java NIO watch Service会同时创建“ENTRY_CREATE”和“ENTRY_MODIFY”吗?

9
我注意到使用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();
    }
}

当我复制一个文件,比如说名字是"abc.txt",日志会显示:
新文件 abc.txt
文件已修改.... abc.txt


非常期待您的回复。

2个回答

5
请查看WatchService JavaDoc中的“平台依赖性”部分。
在您描述的情况下,观察者的行为是正确的。严格来说,当您将文件复制到文件夹中时,文件实际上是被创建然后再修改。
使用WatcherService时需要考虑很多因素,例如:
  • 操作系统
  • 加密磁盘
  • 网络共享
  • ...
请注意以上内容。

3
我认为问题已经在这里得到了回答。
例如Java: WatchService gets informed before content is copied 简而言之,事件是由您的操作系统生成的。您有两个事件,这意味着您的操作系统以非原子方式执行复制。如果您尝试在ENTRY_CREATE和ENTRY_MODIFY之间的某个地方读取文件,它将不一致。但是,这又取决于您的操作系统。例如,在Windows 7上,对于大文件,我会获得一个ENTRY_CREATE和两个ENTRY_MODIFY。 因此,您实际上无法确定文件是否成功复制,您必须提出应用程序/操作系统相关的指标。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接