检查文件是否相同的最快方法是什么?

ojb*_*ass 31 language-agnostic comparison file

如果您有1,000,000个源文件,您怀疑它们都是相同的,并且您想比较它们当前禁用的方法来比较这些文件是什么?假设它们是Java文件和平台,其中进行比较并不重要.cksum让我哭泣.当我的意思相同时我的意思是完全相同.

更新:我知道生成校验和.差异是可笑的...我想要速度.

更新:不要因为它们是源文件而受到限制.举个例子,你假装了一百万次运行非常稳定的程序.您想要证明所有1,000,000个版本的输出都是相同的.

更新:读取块数而不是字节数?Immediatly扔掉那些?这比找到字节数要快吗?

更新:这与比较两个文件的最快方式有什么不同?

Dav*_*d Z 23

我会选择类似cmp程序采用的方法:打开两个文件(比如文件1和文件2),从每个文件中读取一个块,然后逐字节地比较它们.如果它们匹配,则从每个块中读取下一个块,逐个字节地比较它们等.如果到达两个文件的末尾而没有检测到任何差异,请寻找文件1的开头,关闭文件2并打开文件3在它的位置,并重复,直到你检查所有文件.我不认为有任何方法可以避免读取所有文件的所有字节,如果它们实际上完全相同,但我认为这种方法是(或接近)检测可能存在的任何差异的最快方法.

OP修改:提出Mark Bessey的重要评论

"另一个显而易见的优化是,如果文件预计大部分是相同的,如果它们相对较小,则是将其中一个文件完全保留在内存中.这会减少尝试一次读取两个文件的麻烦."

  • 您可能希望在读取文件之前比较大小. (21认同)
  • 另一个明显的优化是,如果文件预期大部分是相同的,并且如果它们相对较小,则将其中一个文件完全保留在内存中.这样可以减少尝试一次读取两个文件的麻烦. (8认同)
  • 没有更快的方法来证明两个文件是相同的,而不是逐字节(duh)比较它们,但对于典型的文件,有概率更快的方法来证明它们*不相同.首先对文件的开头和结尾进行采样,如果文件大部分相同,则会更快地发现差异,但只有一部分(通常是开头或结尾)不同. (3认同)

小智 14

他们的回复中的大多数人都忽略了必须反复比较文件的事实.因此校验和更快,因为校验和被计算一次并存储在存储器中(而不是顺序读取文件n次).

  • @Doug,没有意义,我们仍然需要计算所有一百万个文件的校验和。计算校验和将比直接比较花费更多的时间。 (2认同)
  • OP仅询问是否所有文件都相同。因此,您可以选择一个可以比较所有n-1个文件的文件。因此,如果实际上全部相同,则最多只需要读取全部n个文件即可。如果OP询问了哪些文件相同,我将计算校验和并将其排序以将具有相同校验和的文件分组。 (2认同)

Mic*_*urr 8

假设期望文件将是相同的(听起来就像那个场景),那么处理校验和/哈希是浪费时间 - 它们可能是相同的,你必须重新读取文件以获得最终证明(我也假设因为你想"证明......它们是相同的",将它们哈希到相同的值是不够好的).

如果是这种情况,我认为大卫提出的解决方案非常接近你需要做的事情.在增加复杂程度方面,可以采取一些措施来优化比较:

  • 在进行比较之前检查文件大小是否相同
  • 使用最快的memcmp()(比较单词而不是字节 - 大多数C运行时应该这样做)
  • 使用多个线程来进行内存块比较(最多可达到系统上可用的处理器数量,这会导致你的线程互相争斗)
  • 使用重叠/异步I/O来保持I/O通道尽可能繁忙,但也要仔细配置,以便尽可能少地在文件之间进行抖动(如果文件分为几个不同的磁盘和I/O端口,所有更好)


小智 5

更新:不要因为它们是源文件而受到限制.举个例子,你假装了一百万次运行非常稳定的程序.您想要证明所有1,000,000个版本的输出都是相同的.

如果您可以控制输出,则创建文件/输出的程序会动态创建md5并将其嵌入文件或输出流中,甚至可以通过程序管理输出,该程序沿途创建md5并将其存储在一起数据以某种方式,点是在字节已经在内存中时进行计算.

如果你不能像其他人所说的那样关闭它,检查文件大小然后在相同大小的文件上进行逐字节比较,我不知道任何类型的二进制除法或md5计算是否比直接更好相比之下,你必须触摸每一个字节来证明你以任何方式切割它都是相同的,这样你就可以减少每个字节所需的计算量,并在你发现不匹配时立即获得切断的能力.

如果你计划稍后将这些再次与新输出进行比较,那么md5计算会很有用,但是你基本上回到了第一个尽快计算md5的点