如何使用Java测试文件是否"完整"(完全编写)

Zug*_*dud 28 java

假设您有一个外部进程将文件写入某个目录,并且您有一个单独的进程定期尝试从该目录中读取文件.要避免的问题是读取另一个进程当前正在写出的文件,因此它将是不完整的.当前,读取的进程使用最小文件年龄计时器检查,因此它将忽略所有文件,除非它们的上次修改日期超过XX秒.

我想知道是否有更清洁的方法来解决这个问题.如果文件类型未知(可能是多种不同的格式),是否有一些可靠的方法来检查文件头中应该在文件中的字节数,以及文件中当前确认它们匹配的字节数?

感谢您的任何想法或想法!

Mic*_*ski 12

您可以使用外部标记文件.写入过程可以在开始创建文件XYZ之前创建文件XYZ.lock,并在XYZ完成后删除XYZ.lock.然后,读者可以很容易地知道,只有在相应的.lock文件不存在时才能认为文件是完整的.

  • 如果您无法控制编写程序,该怎么办? (3认同)

Joh*_*lly 11

我过去这样做的方式是编写文件的进程写入"temp"文件,然后在文件写完后将文件移动到读取位置.

因此写入过程将写入info.txt.tmp.完成后,它会将文件重命名为info.txt.然后阅读过程只需要检查info.txt的存在- 它知道如果它存在,它已经完全写入.

或者,您可以让写入进程将info.txt写入另一个目录,如果您不喜欢使用奇怪的文件扩展名,则将其移动到读取目录.


Jos*_*hDM 6

我过去在 Windows 的这种情况下使用的一个简单解决方案是使用boolean File.renameTo(File) 并尝试将原始文件移动到单独的暂存文件夹:

boolean success = potentiallyIncompleteFile.renameTo(stagingAreaFile);
Run Code Online (Sandbox Code Playgroud)

如果successfalse,则potentiallyIncompleteFile仍在写入。


wir*_*d00 5

我无法使用临时标记等,因为客户端通过密钥对SFTP上传文件.它们的尺寸可能非常大.

它相当hacky但我比较睡眠前后几秒钟的文件大小.

它显然不是理想的锁定线程,但在我们的情况下它只是作为后台系统进程运行所以似乎工作正常

private boolean isCompletelyWritten(File file) throws InterruptedException{
    Long fileSizeBefore = file.length();
    Thread.sleep(3000);
    Long fileSizeAfter = file.length();

    System.out.println("comparing file size " + fileSizeBefore + " with " + fileSizeAfter);

    if (fileSizeBefore.equals(fileSizeAfter)) {
        return true;
    }
    return false;
}
Run Code Online (Sandbox Code Playgroud)

注意:如下所述,这可能不适用于Windows.这用于Linux环境.