java - 比较两个大目录并替换相同文件的更有效方法

标签 java file

F:/original_imagesE:/resized_images

我有两个硬盘,其中包含大量目录和图像(jpg)文件,每个总大小约为1.5TB(原始)和400GB(调整大小)

每个文件都有相同的文件名,但大小不同(已调整大小)。然后我必须用原来的替换调整大小的。不幸的是,每个目录层次结构完全不同。

我设法完成了这项工作,但是需要很长时间。我预计几天后就能完成。它有两个循环(Files.walkFileTree()),只是从 A 到 Z 搜索匹配项。一点也不聪明。

public static void main(String[] args) throws IOException {
        FileWriter ostream = new FileWriter("result.txt");
        BufferedWriter out = new BufferedWriter(ostream);

        String fromDir = "F:/original_images";
        String toDir = "E:/resized_images";
        final Path source = Paths.get(fromDir);
        final Path target = Paths.get(toDir);

        Files.walkFileTree(source, EnumSet.of(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE,
                            new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult visitFile(Path sourceFile,
                    BasicFileAttributes attrs) throws IOException {
                // if jpg (there are no jpeg)
                if(sourceFile.toString().toLowerCase().endsWith("jpg")) {

                    // search for the matching file                 
                    // start ** inner of [Files.walkFileTree()]
                    Files.walkFileTree(target, EnumSet.of(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE,
                            new SimpleFileVisitor<Path>() {
                        @Override
                        public FileVisitResult visitFile(Path Targetfile, BasicFileAttributes attrs) throws IOException {

                            if(sourceFile.getFileName().equals(Targetfile.getFileName())) {
                                out.write("replace : [" + sourceFile + "] -> [" + Targetfile + "]");
                                try {
                                    // copy..
                                    Files.copy(sourceFile, Targetfile, REPLACE_EXISTING);
                                }catch(Exception e) {
                                    out.write(e.toString());
                                }
                                // stop searching for this file.
                                return FileVisitResult.TERMINATE;
                            }else
                                return FileVisitResult.CONTINUE;
                        }
                    });
                    // end ** inner of [Files.walkFileTree()]
                }
                return FileVisitResult.CONTINUE;
            }
        });
        out.write("[completed folder] " + fromDir);
        out.close();
    }

我相信一定有更聪明的方法。

(我的猜测是将文件名存储在索引数组中,因为比较速度要快得多。)

你会怎么做?

更新(已解决)

通过采用两个答案的想法,我终于做到了。

源代码太长,无法展示,但简洁的是:

  1. 循环“resized_images”并将 files_info 存储到 hashmap(key:file_name, value:full_Path) 中。

  2. 循环“original_images”并将files_info存储到hashmap中(key:file_name, value:full_Path)。我制作了每个 HashMap 各个子目录以提高效率。

  3. 比较并替换每个“调整大小”和“原始” HashMap 。

结果比以前快了很多。大部分执行时间是在复制文件时。除此之外,整个过程不到 10 分钟。

最佳答案

在我看来,有两个子问题:

  1. 根据通用标准创建 map ,即文件名,例如“a.jpg”
  2. 根据文件名替换另一个目录中调整大小的文件

在上面列出的方法中,您在源目录中递归迭代,我们将其称为外循环。然后,对于源目录中的每个文件,您在目标目录中递归迭代,我们将其称为内部循环。这是一个 O(n2)(读作 n 方的 Big Oh)方法。

另一种简单的方法是创建两个映射(Hashmap),其中键为文件名。因此,您必须分别递归地遍历两个目录,即在单独的循环中。

然后迭代较小的 HashMap ,然后替换调整大小的图像。

这将是一种 O(n) 方法。随着 n 不断增长,您应该会看到所用时间的显着改善。

关于java - 比较两个大目录并替换相同文件的更有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35448679/

相关文章:

java - MyBatis 是否有类似于 Hibernate 中的 "dirty checking mechanism"?

java - Jasper报告连接到mysql时服务器连接失败

java - Hibernate可以批量数据库查询二级缓存中集合未命中的情况吗?

Linux:inode 和 file_inode(file) 的区别?

java - 为什么如果扩展抽象 BaseActivity 全局变量就会变成 null

java - 如何为 Java 6 枚举实现 values()?

java - 文件未写入设备

linux - 在 Linux 中将隐藏文件转换为普通文件

c# - 如何从 .NET 中的 x 行读取文件

java - 使用 Java 将字体写入磁盘(.ttf 文件)