我正在开发一个 Java 进程,该进程应该有效(并递归地)将文件/目录从源位置复制到目标位置。
为此,我想要:
- 创建锁
- 如果目标文件不存在,则复制它
- 如果目标文件不同,则复制它
- 否则它们是相同的,所以什么也不做
- 释放锁
为了检查内容是否相等,我计划使用 Apache Commons IO FileUtils
方法contentsEqual(...)
。为了进行复制,我计划使用 Apache Commons IO FileUtils
方法copyFile(...)
。
所以,我想出的代码是(这仅适用于文件,目录递归地处理到文件的此方法):
private static void checkAndUpdateFile(File src, File dest) throws IOException {
FileOutputStream out = new FileOutputStream(dest);
FileChannel channel = out.getChannel();
FileLock lock = channel.lock();
if (!dest.exists()) {
FileUtils.copyFile(src, out);
} else if (!FileUtils.contentEquals(src, dest)) {
FileUtils.copyFile(src, out);
}
lock.release();
channel.close();
out.close();
}
这会执行文件锁定(很棒),并复制文件( super )。
但是,每当复制文件时,它都会将复制文件的上次修改时间戳设置为复制时间。这意味着后续调用 FileUtils.contentEquals(src, dest)
继续返回false
,因此文件被重新复制。
我真正想要的类似于 FileUtils.copyFile(src, dest, true)
,它保留文件时间戳 - 并且通过调用 FileUtils.contentEquals(src, dest) 得到 true。这需要将锁锁定在 File
上,而不是 FileOutputStream
上,否则会调用 FileUtils.copyFile(src, dest, true)
由于文件被锁定而失败并引发异常。
或者,我考虑执行 FileUtils.copyFile(src, dest, true)
方法的操作,即调用 dest.setLastModified(src.lastModified())
。但是,这必须在锁释放后调用,如果同一个进程同时执行多次,这可能会导致问题。
我也考虑过将锁放在源文件上,但这并没有帮助,因为我必须将它放在 FileInputStream
上,并且我想传递一个 文件
到FileUtils.copyFile(src, dest)
。
所以:
- 有没有更简单的方法来实现我想要做的事情?
- 是否可以对文件而不是文件的派生对象加锁?
- 解决这个问题的最佳方法是什么?
- 即我只需要为此编写自己的方法吗? (可能是
copyFile(...)
)
- 即我只需要为此编写自己的方法吗? (可能是
最佳答案
您可以使用Guava Google Core Library
来比较两个文件。
ByteSource inByte = Resources.asByteSource(srcFileURL);
ByteSource outByte = Files.asByteSource(srcFileURL2);
boolean fileEquals= inByte.contentEquals(outByte));
关于java - 在Java中使用文件锁复制文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20471374/