如何判断文件何时“完成”复制到监视目录?

我正在使用WatchService API来监视目录,并在用户开始将文件复制到目录中时获取ENTRY_CREATE事件。 我正在使用的文件可能很大,我想知道副本何时完成。 是否有任何内置的java API可用于实现此目的,或者我最好只是跟踪创建的文件的大小并在大小停止增长时开始处理?

编辑:这是我的示例代码:

package com.example; import java.io.File; import java.nio.file.FileSystems; import java.nio.file.Path; import java.nio.file.StandardWatchEventKinds; import java.nio.file.WatchEvent; import java.nio.file.WatchKey; import java.nio.file.WatchService; public class Monitor { public static void main(String[] args) { try { String path = args[0]; System.out.println(String.format( "Monitoring %s", path )); WatchService watcher = FileSystems.getDefault().newWatchService(); Path watchPath = FileSystems.getDefault().getPath(path); watchPath.register(watcher, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_MODIFY); while (true) { WatchKey key = watcher.take(); for (WatchEvent event: key.pollEvents()) { Object context = event.context(); System.out.println( String.format( "Event %s, type %s", context, event.kind() )); } } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } 

哪个产生这个输出:

 Monitoring /Users/ericcobb/Develop/watch Event .DS_Store, type ENTRY_MODIFY Event 7795dab5-71b1-4b78-952f-7e15a2f39801-84f3e5daeca9435aa886fbebf7f8bd61_4.mp4, type ENTRY_CREATE 

创建条目后,您将获得ENTRY_CREATE事件。 对于每个后续修改,您将获得ENTRY_MODIFY事件。 复制完成后,您将收到ENTRY_MODIFY通知。

  • 我认为最常见的方法是将文件复制到同一分区上的临时目录中,然后通过primefaces移动命令将其移动到受监视的目录。
  • 也许通过使用文件时间戳来实现解决方案

然而,这两种解决方案都需要在书写应用程序中实现。 我认为你无法从阅读申请中确切地说出来。

这是我们今天使用的库:

https://github.com/levelsbeyond/jpoller

它是原始作者不再维护的开源项目的分支。 我们已经修复了一些错误,现在在生产中使用它。

它的工作原理是检查目录中文件的大小,并在文件大小停止增长一段时间后认为文件已完成(准备处理)。

确保没有其他进程正在写入文件的唯一有效选项是成功获取文件的写锁定。 虽然有点笨拙,但您可以将FileChannel和FileLock用于此目的

 try(FileChannel ch = FileChannel.open(p, StandardOpenOption.WRITE); FileLock lock = ch.tryLock()){ if(lock == null) { //no lock, other process is still writing } else { //you got a lock, other process is done writing } } catch (IOException e) { //something else went wrong } 

您也可以使用阻塞调用ch.lock()来获取锁。 但是,由于在写入文件时会不断生成ENTRY_MODIFY事件,因此您也可以使用tryLock并等待下一个事件。

也许您可以通过尝试获取文件的写入权限来判断,但这取决于两个因素并需要研究:

  1. 编写应用程序必须获取对文件的独占写入权限,并且在文件实际完成之前不得关闭该文件。
  2. 必须可以从Java进行测试。 我会试一下,如果文件仍被锁定以供另一个程序写入,是否将文件作为 WRITE访问的FileChannel抛出会引发exception。 不幸的是,Javadoc没有详细说明这一点。
 File file = child.toAbsolutePath().toFile(); if(file.isFile() && file.isWrite()) { } 

也许这将是找出你想要什么但不在while语句中的方法。

当您真正访问文件时它将起作用。