[英]How to one-way synchronize files in two directory structures in java?
我有两个文件夹,源文件夹和目标文件夹,其中包含文件和可能的子文件夹(假定目录结构相同,子文件夹和文件可以进入任何深度)。 我们要同步目标,以便对所有文件:
Exists in source, but not in target -> new, copy over to target Exists in target, but not in source -> deleted, delete from the target Exists in both, but binary unequal -> changed, copy over from source Exists in both, and is binary equal -> unchanged, leave be
我遇到的一个问题是检查文件是否存在(listFiles()的返回值似乎未定义contains()),但是要引用其他目录结构则是更大的障碍。 例如,当遍历源文件夹并在那里找到目标文件夹时,我将如何检查目标文件夹是否包含文件“ foo.txt”? 这是我到目前为止的内容:
public void synchronize(File source, File target) {
//first loop; accounts for every case except deleted
if (source.isDirectory()) {
for (File i : source.listFiles()) {
if (i.isDirectory()) {
synchronize(i, /**i's equivalent subdirectory in target*/);
}
else if (/**i is new*/) {
/**Copy i over to the appropriate target folder*/
}
else if (/**i is different*/) {
/**copy i over from source to target*/
}
else {/**i is identical in both*/
/**leave i in target alone*/
}
}
for (File i : target.listFiles()) {
if (/**i exists in the target but not in source*/) {
/**delete in target*/
}
}
}
}
编辑(重要):我感谢你们提供的所有答案,但主要问题仍未解决:引用另一个目录,即注释中的内容。 h22的答案似乎在球场的某个地方,但这还不够,如下面评论中所述。 如果有人可以用更小的字眼解释这个问题,我将不胜感激。 从经验来看,这恰恰是一个精通Java的人可以在五分钟内解决的问题,而我将花两个令人沮丧的一周来重新发现美国。
正如wero所指出的,您可以使用aFile.exists()
来查看给定路径是否存在。 您还应该将其与aFile.isFile()
结合使用,以检查路径是否为普通文件(而不是文件夹)。
检查内容是否相等比较棘手。 我提出以下建议:
boolean sameContents(File fa, File fb) throws IOException {
Path a = a.toPath();
Path b = b.toPath();
if (Files.size(a) != Files.size(b)) return false;
return Arrays.equals(
Files.readAllBytes(a), Files.readAllBytes(b));
}
但是只有在文件很小的情况下才可以; 否则,您可能会用尽内存尝试一次性比较它们(需要使用Arrays.equals
)。 如果其中有大文件,则此答案建议使用Apache Commons IO的FileUtils.contentEquals()
。
请注意,以上代码和contentEquals
仅比较文件,而不比较文件夹。 要比较文件夹,您将需要使用递归,在每个相同名称,相同大小的文件上调用sameContents
或等效项,并且如果在源或目标中均未找到与特定路径名匹配的内容, sameContents
。
如果源目录中有目标目录File targetDir
和源文件File sourceFile
,则可以通过以下操作检查相应目标文件是否存在:
File targetFile = new File(targetDir, sourceFile.getName());
boolean exists = targetFile.exists();
仅以递归方式访问源文件夹。 剥离文件夹根目录并直接寻址目标位置:
String subPath = sourceFile.getAbsolutePath().substring(sourceRoot.length);
File targetFile = new File(targetRoot + File.separator + subPath);
if (targetFile.getParentFile().exists()) {
targetFile.getParentFile().mkdirs();
}
// copy, etc
否则,如果目标位置缺少所需的分层文件夹结构(可能会深入许多目录),则可能会遇到困难。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.