检查文件是否完整写入

Vik*_*bin 22 java filesystems io file

目前我正在研究在其中一个例程中处理源目录中的文件的项目.有一个Java进程正在查找指定的目录,并尝试读取和处理文件(如果存在).文件退出大,并由其他第三方进程更新.问题是如何检查文件是否完整写入?我试图使用file.length()但看起来即使写入过程尚未完成它返回实际大小.我觉得解决方案应该依赖于平台.任何帮助,将不胜感激.

更新:这个问题与副本没有什么不同,但它有一个高评级的工作代码片段的答案.

Vik*_*bin 20

我得到了解决方案:

private boolean isCompletelyWritten(File file) {
    RandomAccessFile stream = null;
    try {
        stream = new RandomAccessFile(file, "rw");
        return true;
    } catch (Exception e) {
        log.info("Skipping file " + file.getName() + " for this iteration due it's not completely written");
    } finally {
        if (stream != null) {
            try {
                stream.close();
            } catch (IOException e) {
                log.error("Exception during closing file " + file.getName());
            }
        }
    }
    return false;
}
Run Code Online (Sandbox Code Playgroud)

感谢@cklab和@Will以及所有其他建议以"独家锁定"方式查看的人.我刚刚在这里发布代码,让其他人对使用它感兴趣.我相信@tigran建议的重命名解决方案也适用,但纯Java解决方案对我来说更合适.

PS最初我使用FileOutputStream而不是RandomAccessFile锁定正在写入的文件.

  • 这适用于Winows但不适用于Linux. (3认同)
  • 我已经在 Windows 中尝试过这个解决方案并且工作正常,但是如果源文件处于“只读”模式,它将永远不会处理它。这种情况有解决方案吗? (2认同)
  • 解决方案应与平台无关。 (2认同)

Wil*_*ill 10

生成器进程在完成写入后是否关闭文件?如果是这样,如果生产者进程仍在生成,则尝试使用独占锁打开使用者进程中的文件将失败.

  • 这不是一个非常有用的正确答案:( (2认同)

Jos*_*hDM 5

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

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

如果successfalse,则potentiallyIncompleteFile仍在写入。

  • 这就是为什么我的答案是“使用 Windows”而不是“适用于所有系统”。 (2认同)