繁体   English   中英

如何在Java中的两个目录结构中单向同步文件?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM