【问题标题】:What is the fastest method to compare two large files in Java [closed]在Java中比较两个大文件的最快方法是什么[关闭]
【发布时间】:2017-11-30 18:10:53
【问题描述】:

目前,我们每晚进行一次自动化运行,对我们的软件生成的测试文件和基线文件进行比较。这种比较进行了多次,文件很大。文件比较是我们测试自动化的瓶颈。

文件比较目前是通过逐行比较缓冲来完成的。

我正在考虑对两个文件进行校验和比较(然后逐行检查校验和是否不匹配)。这是最好的方法吗?有没有人想推荐的公共图书馆?

谢谢

【问题讨论】:

  • 文件必须相同还是不同?你必须看到差异吗?
  • 请定义“大”。如果已经预先计算了校验和,那么比较校验和是最好的方法,如果您必须先计算它们,那肯定是性能最低的方法之一。
  • 您可以从检查文件大小开始,如果它们不匹配它们已经不同,那么整个文件的校验和也是检查相等性的好方法
  • 逐行可能意味着根据某些字符编码将文件字节转换为字符,查找换行符,创建表示不再需要行时必须进行垃圾收集的行的字符串等.,因此切换到较低级别的字节缓冲区 I/O 可能会提高速度 - 但首先使用分析器找出这是否是瓶颈......
  • 恕我直言,对于必须相等(逐字节)且大小高达几百千字节的文件,我首先会比较它们的大小,如果它们相等,只需分配两个大小合适的字节数组,完整读取文件并比较字节数组。对于较大的文件,我会分配两个可能为 128KB 的块缓冲区并逐块读取文件,直到块不同或文件被完全读入。

标签: java checksum file-comparison


【解决方案1】:

10 毫秒足以比较两个 260K 文件吗? (在 Windows 笔记本电脑上)

如果是这样,您可以使用java.security.DigestInputStream 来计算和比较哈希。

当然可以,之前检查文件长度。 如果问题是您需要比较许多文件,请考虑使用并行线程来比较每一对。

示例代码:

public static void main(String[] args) {

    try {
        File file1 = new File("D:\\tmp\\tests\\logs\\test.log");
        File file2 = new File("D:\\tmp\\tests\\logs\\test-cp.log");

        if (!file1.exists() || !file2.exists()) {
            System.out.println("One of the file not found.");
            return;
        }
        if (file1.length() != file2.length()) {
            System.out
                    .println("Files are not identical - not equal length.");
            return;
        }

        long f1Length = file1.length();
        long f2Length = file2.length();

        System.out.println("Check Digest method:");
        FileInputStream fis1 = new FileInputStream(file1);
        DigestInputStream dgStream1 = new DigestInputStream(fis1,
                MessageDigest.getInstance("MD5"));
        FileInputStream fis2 = new FileInputStream(file2);
        DigestInputStream dgStream2 = new DigestInputStream(fis2,
                MessageDigest.getInstance("MD5"));
        // most expensive is dgStream1.getMessageDigest() so do it only at last read
        dgStream1.on(false);
        dgStream2.on(false);

        long f1ReadTotal = 0;
        long f2ReadTotal = 0;

        long start = System.nanoTime();

        int read = 0;
        byte[] buff = new byte[1024 * 128];
        do {
            if ((f1Length - f1ReadTotal) < (1024 * 128)) {
                // last read 
                dgStream1.on(true);
            }
            read = dgStream1.read(buff);
            f1ReadTotal += read > 0 ? read : 0;
        } while (read > 0);

        read = 0;
        do {
            if ((f2Length - f2ReadTotal) < (1024 * 128)) {
                // last read
                dgStream2.on(true);
            }
            read = dgStream2.read(buff);
            f2ReadTotal += read > 0 ? read : 0;
        } while (read > 0);

        long runTime = System.nanoTime() - start;
        if (Arrays.equals(dgStream1.getMessageDigest().digest(), dgStream2
                .getMessageDigest().digest())) {
            System.out.println("Files are identical. completed in "
                    + (runTime / 1000000) + " ms. [" + runTime + " ns.]");
        } else {
            System.out.println("Files are not identical. completed in "
                    + (runTime / 1000000) + " ms. [" + runTime + " ns.]");
        }

        fis1.close();
        fis2.close();

    } catch (Exception e) {
        e.printStackTrace();
    }

}

getMessageDigest() 是最耗时的操作,因此请在最后一次阅读时执行一次。

顺便说一句:代码只是一个想法。真正的代码必须更加小心,尤其是“最后一次读取”,并且绝对可以更优化。

【讨论】:

    猜你喜欢
    • 2023-03-29
    • 2021-03-15
    • 1970-01-01
    • 1970-01-01
    • 2012-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多