逐行比较两个文件(不按顺序排列)的最有效方法是什么?[已结束]

What is the most effective way to compare two files line by line (lines are not ordered)? [closed]

提问人:Andres Acosta 提问时间:3/2/2023 更新时间:3/2/2023 访问量:303

问:


想改进这个问题吗?更新问题,以便可以通过编辑这篇文章来用事实和引文来回答。

9个月前关闭。

我有两个文件,大约有 20,000 行,我需要比较它们,问题是这些行的顺序不同,每一行都是唯一的,因为它们是 DB 的记录,但文件一的行可以是第二个文件中的第 15.000 行,我试图浏览第一个文件的一行,并使用BufferReader但是对于每行大约需要10秒17.000次会很长的时间,有没有更有效的方法可以做到这一点? .

Java 文件 比较

评论

0赞 Scary Wombat 3/2/2023
因为它们是数据库的记录 - 检索已排序的数据。然后快速失败。
0赞 undefined symbol 3/2/2023
“比较”它们的预期结果是什么?您只是想确定哪些行是/不是在两者中吗?将第一个文件逐行加载到 HashSet 中,然后依次查找第二个文件中的每一行。
0赞 tla 3/2/2023
比较的结果是什么?您只想知道这些行集是否相同,还是发现其他文件中缺少的行?文件可以包含重复的行吗,您希望如何处理它们?
2赞 Bohemian 3/2/2023
这能解决您的问题吗?bash -c 'diff <(sort text2) <(sort text1)'
0赞 Andres Acosta 3/2/2023
@undefined符号 是的,数据经过多个数据库,所以文件 1 是其中一个数据库中的数据,文件 2 是另一个数据库中的数据,所以我需要验证数据是否相同,每一行都是一条记录,但我不能使用 HashSet,因为我无法加载内存中的所有数据,因为数据太多,所以它会以记忆错误结束。

答:

2赞 impossible-sudoku 3/2/2023 #1

使用哈希函数

  1. 为第一个文件中的每一行生成一个哈希值。您可以使用 MD5 或 SHA-1 等哈希函数
  2. 将哈希值存储在哈希表或字典数据结构中,以哈希值为键,以行号为值。
  3. 循环访问第二个文件中的每一行,为每行生成一个哈希值,并检查是否与 file1 字典匹配

法典

import java.io.*;
import java.nio.file.Files;
import java.security.MessageDigest;
import java.util.HashMap;

public class FileComparator {
    public static void main(String[] args) throws Exception {
        File file1 = new File("file1.txt");
        File file2 = new File("file2.txt");

        HashMap<String, String> file1Hashes = getFileHashes(file1);
        HashMap<String, String> file2Hashes = getFileHashes(file2);

        for (String key : file1Hashes.keySet()) {
            if (!file2Hashes.containsKey(key)) {
                System.out.println(key + " not found in file2");
            } else if (!file1Hashes.get(key).equals(file2Hashes.get(key))) {
                System.out.println(key + " differs in file1 and file2");
            }
        }

        for (String key : file2Hashes.keySet()) {
            if (!file1Hashes.containsKey(key)) {
                System.out.println(key + " not found in file1");
            }
        }
    }

    private static HashMap<String, String> getFileHashes(File file) throws Exception {
        HashMap<String, String> hashes = new HashMap<>();
        BufferedReader reader = new BufferedReader(new FileReader(file));

        String line;
        while ((line = reader.readLine()) != null) {
            hashes.put(line, getHash(line));
        }

        reader.close();
        return hashes;
    }

    private static String getHash(String line) throws Exception {
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        byte[] hashBytes = md.digest(line.getBytes());
        StringBuilder sb = new StringBuilder();

        for (byte b : hashBytes) {
            sb.append(String.format("%02x", b));
        }

        return sb.toString();
    }
}

评论

0赞 impossible-sudoku 3/2/2023
这对你不起作用?
0赞 Andres Acosta 3/2/2023
这不会以内存问题结束吗?我的意思是在地图中存储 17,000 个项目,可以吗?
0赞 impossible-sudoku 3/2/2023
我的意思是,现在大多数计算机至少有几GB内存。
1赞 alalalala 3/2/2023
或者最好用行的哈希值作为键,遍历第一张地图,然后用第一张地图的键从第二张地图中获取
1赞 Andres Acosta 3/2/2023
@impossible-sudoku 我接受了你的请求,但我使用 String.hashCode() 值作为每行的键,它工作正常,非常感谢。