c# - 比较大文件的内容

标签 c# binary compare large-files

我需要比较非常大的文件的内容。程序的速度很重要。我需要100%匹配。我看了很多资料,但没有找到最优解。我正在考虑两个选择和两个问题。

  1. 逐字节比较整个文件 - 对于大文件来说速度不够快。
  2. 使用哈希比较文件 - 不是 100% 匹配具有相同哈希的两个文件。

您有什么建议?也许我可以使用线程? MemoryMappedFile 有帮助吗?

最佳答案

如果您真的需要 100% 保证文件 100% 相同,那么您需要进行逐字节比较。这只是问题中包含的 - 唯一错误匹配风险为 0% 的哈希方法是身份函数!

我们剩下的是可以快速给我们快速答案的捷径,让我们在某些的时候跳过字节对字节的比较。

通常,证明相等性的唯一捷径是证明同一性。在 OO 代码中,将显示两个对象,而实际上是同一个对象。文件中最接近的是绑定(bind)或 NTFS 连接是否意味着两个路径指向同一个文件。这种情况很少发生,除非工作的性质使它比正常情况更常见,否则检查不会带来净 yield 。

因此,我们在寻找不匹配方面走捷径。不会增加我们的通过次数,但会使我们的失败速度更快:

  1. 不同的大小,而不是字节对字节相等。简单!
  2. 如果您要多次检查同一个文件,则对其进行哈希处理并记录哈希值。不同的hash,保证不相等。需要一对一比较的文件数量大幅减少。
  3. 许多文件格式可能有一些共同点。特别是许多格式的第一个字节往往是“魔数(Magic Number)”、标题等。要么跳过它们,要么跳过然后然后检查最后(如果它们有可能不同但它很低)。

然后是尽可能快地进行实际比较的问题。一次将 4 个八位字节的批处理加载到一个整数中并进行整数比较通常比一个八位字节一个八位字节更快。

线程可以提供帮助。一种方法是将文件的实际比较拆分为多个操作,但如果可能的话,通过在不同线程中进行完全不同的比较会发现更大的 yield 。我需要更多地了解您正在做的事情才能提供更多建议,但最主要的是确保测试的输出是线程安全的。

如果您确实有多个线程检查相同的文件,请让它们彼此分开工作。例如。如果你有四个线程,你可以将文件分成四个,或者你可以让一个占用字节 0、4、8,而另一个占用字节 1、5、9 等(或 4 字节组 0、4、8 等) ).后者更有可能有 false sharing问题比前者大,所以不要那样做。

编辑:

这还取决于您对文件的处理方式。你说你需要 100% 的确定性,所以这一点不适用于你,但对于更普遍的问题,如果误报的成本是资源、时间或内存的浪费而不是实际的失败,则值得添加, 然后通过模糊的捷径减少它可能是一个净赢,并且值得进行分析以查看是否是这种情况。

如果您使用散列来加快速度(它至少可以更快地找到一些明确的不匹配),那么 Bob Jenkins' Spooky Hash是个不错的选择;它不是加密安全的,但如果这不是您的目的,它会非常快速地创建 128 位哈希(比加密哈希快得多,甚至比许多 GetHashCode() 实现所采用的方法快得多)非常擅长避免意外碰撞(加密哈希避免的那种故意碰撞是另一回事)。我为 .Net 实现了它 and put it on nuget因为当我发现自己想要使用它时,其他人都没有。

关于c# - 比较大文件的内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12116699/

相关文章:

c# - 在 C# 中向 Dictionary<string, T> 添加通用对象 - 空引用异常

c# - 如果 List<T> 的大小已知,是否值得初始化它的集合大小?

c++ - 将一个结构写成二进制,其中一个成员是一个字符串?

c++ - 如何检查C++编译器生成的代码?

Bash 比较运算符始终为 true

c# - RedirectToAction 不传递参数 MVC

c# - Redis MSET 相当于 SET 或 LIST?

c++ - g++ 二进制输出分析

c - 在 c 中比较不相等的 char 数组的正确方法

java - 如果字符串具有相同的前缀和后缀,则删除字符串的最后 3 个字符