我试图复制&将一个非常小的文件粘贴到一个文件夹中,该文件夹由手表服务观察到。第一次效果很好,但在以下所有副本上&粘贴操作,我得到一个异常,即另一个进程已经处理了该文件。通过实验,我发现当Windows创建文件时,我的服务会得到通知,而不是当复制文件内容时。如果我锁定该文件,Windows将无法复制任何数据,并且该文件为空。另一方面,如果我把文件移到目录中,一切都会很好。
这是Windows的错误吗?我无法在mac或Linux工作站上测试它。或者可能只是我没有能力。感谢您的帮助。
我的代码如下所示:
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();
}
}
复制操作并不总是原子操作。
使用原子复制(或移动),您将获得一个ENTRY_CREATE事件,该事件引用的文件将是完整的,可供读取。
如果副本不是原子副本,则在创建文件时将收到一个ENTRY_CREATE事件,然后在通过复制操作写入文件时会收到一个或多个ENTRY_MODIFY事件。
没有简单的方法可以确定复制操作何时完成对文件的写入并将其释放。根据操作系统和文件系统的不同,当文件被复制操作锁定时,试图打开进行读取时,您可能会得到FileNotFoundException,或者您可以成功打开文件,但当您实际读取时,会得到部分内容。
您将不得不实现一些启发式方法,比如尝试在ENTRY_CREATE之后立即读取文件,如果初始读取失败,则重新安排稍后的读取时间。