Java:在复制内容之前,WatchService会获得通知 [英] Java: WatchService gets informed before content is copied

查看:120
本文介绍了Java:在复制内容之前,WatchService会获得通知的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试将一个非常小的文件复制并粘贴到一个监视服务所观察的文件夹中。第一次运行很好,但在所有后续复制和粘贴操作,我得到一个异常,另一个进程已经处理该文件。通过实验,我发现在Windows创建文件时通知我的服务,而不是在复制内容时通知我的服务。如果我锁定文件,Windows无法复制任何数据,文件为空。另一方面,如果我将文件移动到目录中,一切正常。

I've tried to copy&paste a very small file into a folder which is observed by a watch service. The first time works great, but on all following copy&paste actions, i get an exception that another process handles the file already. With experiments I've found out that my service is informed when Windows creates the file and not when its content is copied. If I lock the file, Windows isn't able to copy any data and the file is empty. On the other hand, if I move the file into the directory, everything works fine.

这是来自Windows的错误吗?我无法在mac或Linux工作站上测试它。或者也许只是我无能为力。任何帮助表示赞赏。

Is that a bug from Windows? I wasn't able to test it on a mac or Linux workstation. Or maybe it was just me being incapable. Any help is appreciated.

我的代码如下所示:

try (WatchService watchService = importPath.getFileSystem().newWatchService()) {
  importPath.register(watchService, StandardWatchEventKinds.ENTRY_CREATE);
  handleExistingFiles();

  try {
    do {
      WatchKey watchKey = watchService.take();
      if (!watchKey.isValid()) {
        continue;
      }

      boolean hasCreationEvents = false;
      for (WatchEvent<?> event : watchKey.pollEvents()) {
        hasCreationEvents |= event.kind().equals(StandardWatchEventKinds.ENTRY_CREATE);
      }
      watchKey.reset();

      if (hasCreationEvents) {
        handleNewFiles();
      }
    }
    while (!Thread.currentThread().isInterrupted());
  }
  catch (InterruptedException ignoredEx) {
    Thread.currentThread().interrupt();
  }
}


推荐答案

复制操作并不总是原子的。

The copy operation is not always atomic.

使用原子复制(或移动),您将获得一个ENTRY_CREATE事件,该事件引用的文件将完整并可供读取。

With atomic copy (or move) you will get a single ENTRY_CREATE event and the file referenced by the event will be complete and available for reading.

如果副本不是原子的,您将在创建文件时收到ENTRY_CREATE事件,然后在写入文件时收到一个或多个ENTRY_MODIFY事件通过复制操作。

If the copy is not atomic, you will receive an ENTRY_CREATE event when the file is created and then you will receive one or more ENTRY_MODIFY events while the file is being written by the copy operation.

没有简单的方法来确定复制操作何时写入文件并将其释放。根据操作系统和文件系统,在复制操作锁定文件时尝试打开文件进行读取时可能会出现FileNotFoundException,或者您可以成功打开文件,但实际读取时会得到部分内容。

There is no easy way to determine when the copy operation has finished writing to a file and released it. Depending on the OS and file system you could get FileNotFoundException when trying to open a file for reading while it is locked by the copy operation or you could successfully open a file but you will get partial contents when you actually read it.

您必须实施一些启发式方法,例如在ENTRY_CREATE之后立即尝试读取文件,并在初始读数失败时重新安排读数。

You will have to implement some heuristics like trying to read a file immediately after ENTRY_CREATE and rescheduling the reading for some later time if the initial reading failed.

这篇关于Java:在复制内容之前,WatchService会获得通知的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆