如何在java中知道文件复制是否“正在进行”/是否已完成(1.6)

2022-09-04 02:07:45

我正在java(1.6)中编写一个目录监视实用程序,使用轮询以特定的间隔使用长值作为更改的指示。我发现,当我的轮询间隔很小(秒)并且复制的文件很大时,则在文件复制实际完成之前触发更改事件。lastModified

我想知道是否有一种方法可以找到文件的状态,例如正在传输,完成等。

环境: Java 1.6;预计将在Windows和Linux上工作。


答案 1

我过去使用过两种与平台无关的方法。

1/ 这是针对FTP传输的,我控制了放置的内容,因此它可能不直接相关。

基本上,无论放一个文件是什么,当它完成时,也会放一个小的(可能是零字节的)虚拟文件,称为(例如)。file.txtfile.txt.marker

这样,监视工具只需查找要显示的标记文件,当它出现时,它就知道真实文件已完成。然后,它可以处理真实文件并删除标记。

2/ 持续时间不变。

让监视器程序等待,直到文件保持不变 N 秒(其中 N 可以合理地保证足够大,以至于文件完成)。

例如,如果文件大小在 60 秒内未更改,则很有可能它已完成。

在不认为文件已经完成,只是因为文件上没有活动,以及一旦文件完成即可开始处理它之间有一个平衡行为。与 FTP 相比,这对于本地复制来说问题不大。


答案 2

这个解决方案对我有用:

File ff = new File(fileStr);

if(ff.exists()) {

    for(int timeout = 100; timeout>0; timeout--) {
        RandomAccessFile ran = null;

        try {
            ran = new RandomAccessFile(ff, "rw");
            break; // no errors, done waiting
        } catch (Exception ex) {
            System.out.println("timeout: " + timeout + ": " + ex.getMessage());
        } finally {
            if(ran != null) try {
                ran.close();
            } catch (IOException ex) {
                //do nothing
            }

            ran = null;
        }

        try {
            Thread.sleep(100); // wait a bit then try again
        } catch (InterruptedException ex) {
            //do nothing
        }
    }

    System.out.println("File lockable: " + fileStr +
                 (ff.exists()?" exists":" deleted during process"));
} else {
    System.out.println("File does not exist: " + fileStr);
}

此解决方案依赖于这样一个事实,即如果另一个进程打开了文件,则无法打开该文件进行写入。它将一直保持在循环中,直到达到超时值或可以打开文件。超时值需要根据应用程序的实际需求进行调整。我也尝试了这种方法与通道和tryLock(),但它似乎没有必要。