【问题标题】:"Fastest" hash function implemented in Java, comparing part of file用Java实现的“最快”哈希函数,比较部分文件
【发布时间】:2011-04-12 08:48:36
【问题描述】:

我需要在 Java 中比较实例“文件”的两个不同文件,并希望使用快速哈希函数来做到这一点。

想法: - 散列文件 1 中的前 20 行 - 散列文件 2 中的前 20 行 - 比较两个哈希值,如果相等则返回 true。

我想使用 Java 中实现的“最快”哈希函数。你会选择哪一个?

【问题讨论】:

  • 对不起,但这只是一个可怕的想法。无论您使用什么散列函数,产生冲突都是微不足道的。不妨将文件的前 10 个字符作为其“哈希”。
  • 您对要比较的文件了解多少?您可以做的第一件事就是使用文件大小作为哈希的一部分。在文件系统上的数万个(或数十万个)文件中,具有相同文件大小的两个文件的百分比非常非常低...

标签: java performance comparison hash-function


【解决方案1】:

如果你想要速度,不要散列!尤其不是像 MD5 这样的加密哈希。这些哈希被设计为无法逆转,计算速度不快。您应该使用的是校验和 - 请参阅 java.util.zip.Checksum 及其两个具体实现。 Adler32 的计算速度非常快。

任何基于校验和或哈希的方法都容易发生冲突,但您可以像 RSYNC 那样使用两种不同的方法,从而将风险降至最低。

算法基本上是:

  • 检查文件大小是否相等
  • 将文件分成大小为 N 字节的块
  • 计算每对匹配块的校验和并进行比较。任何差异都证明文件不一样。

这样可以及早发现差异。您可以通过使用不同的算法或不同的块大小一次计算两个校验和来改进它。

结果中的更多位意味着发生冲突的机会更少,但是一旦超过 64 位,您就超出了 Java(和计算机的 CPU)可以本机处理的范围,因此变得很慢,因此 FNV-1024 的可能性较小给你一个假阴性,但要慢得多。

如果只关注速度,只需使用 Adler32 并接受很少会检测不到差异的事实。这真的很罕见。此类校验和用于确保互联网能够发现传输错误,以及您多久会收到错误数据?

这真的与准确性有关,您必须比较每个字节。其他都行不通。

如果您可以在速度和准确性之间做出妥协,那么有很多选择。

【讨论】:

  • 很棒的答案!我尝试了 MD5 和 SHA-1 来散列文件,但它们对于 SSH 的读取速度来说太慢了。事实证明,使用 CRC 快了很多。您也对策略进行了很好的概述。竖起大拇指。
  • 哦,好吧,还有对这个真棒答案的扩展:为了使冲突非常不可能,只需使用不同的“N”运行两次 RSYNC 算法。所以之前,您的碰撞概率在1:2^64 中的某个位置,现在它将在1:2^128 中。粗略估计。
【解决方案2】:

如果您在同一系统上同时比较两个文件,则无需对它们进行哈希处理。只需在读取两个文件时比较两个文件中的字节是否相等。如果您想在不同时间比较它们或者它们在不同的地方,那么 MD5 既快速又足够。除非您正在处理非常大的文件,否则没有太多理由需要更快的文件。甚至我的笔记本电脑每秒也可以散列数百兆字节。

如果您想验证它们是否相同,您还需要对整个文件进行哈希处理。否则,如果您想快速检查,不妨只检查大小和上次修改时间。如果文件真的很大并且您相信中间不会改变,您也可以检查文件的开头和结尾。如果您不处理数百兆字节,您不妨检查每个文件的每个字节。

【讨论】:

  • 我需要在不同的时间和地点比较这些文件,所以我猜散列是这里的最佳选择。我正在考虑 MD5,但如果有更快的话,我想做一些研究。感谢您的回答!
  • 啊,好的。是的,MD5 可能会很好。如果你真的在处理大文件,这里有Fast MD5 Implementation in Java。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-02
  • 2016-03-25
  • 2017-03-25
  • 2013-03-04
  • 1970-01-01
  • 2011-01-19
相关资源
最近更新 更多