簡體   English   中英

比較兩個巨大目錄並替換相同文件的更有效方法

[英]More efficient way to compare two huge directories and replace same files

F:/original_imagesE:/resized_images

我有兩個硬盤,其中包含很多目錄和image(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)中。 為了提高效率,我為每個子目錄制作了每個哈希圖。

  3. 比較並替換每個“調整大小”和“原始”哈希圖。

結果比以前快得多。 大多數執行時間是在復制文件時。 除此之外,它不到10分鍾。

我的觀察方式有兩個子問題:

  1. 根據常見標准創建一個地圖,即文件名,例如“ a.jpg”
  2. 根據文件名替換大小調整后的另一個目錄

在上面列出的方法中,您在源目錄中遞歸地進行迭代,我們稱其為外循環。 然后,對於源目錄中的每個文件,您都在目標目錄中進行遞歸迭代,讓我們將其稱為內部循環。 多數民眾贊成在O(n2)(讀為n平方的大哦)方法。

另一種簡單的方法可能是,創建兩個映射(哈希映射),鍵為文件名。 因此,您將必須遞歸地分別遍歷兩個目錄,即分別遍歷循環。

然后遍歷較小的哈希圖,然后替換調整大小的圖像。

那將是一種O(n)方法。 隨着n的不斷增長,您應該看到所花費的時間有了顯着的改善。

如Sanket Naik所述,為原始圖像創建一個Map。 我不確定您的實現效果如何,但是您可以在mkyong中輕松編輯代碼。

Map存儲中,將image_name.jpg作為key並將其its_directory作為值。 例如, img1.jpg位於F:/original_images/dir1/dir2/dir3/ ,相應的條目應為img1.jpg, /dir1/dir2/dir3/

然后,

for each entry in resized image directory{
    value = map.get(entry);
    replaceImage(path/to/entry/+entry, value+entry);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM