PHP:来自 ZipArchive::statIndex() 的 CRC 是否足够独特以用于检测许多 zip 中的重复文件?

PHP: Is the CRC from ZipArchive::statIndex() unique enough to be used to detect duplicate files in many zips?

如果我有多个 zip 文件并且我遍历每个文件的内容以找到唯一的文件,那么不同 zip 中的同一文件的 CRC 值是否相同?

ZipArchive 上的 statindex 方法 returns 像这样的数组:

Array
(
    [name] => foobar/baz
    [index] => 3
    [crc] => 499465816
    [size] => 27
    [mtime] => 1123164748
    [comp_size] => 24
    [comp_method] => 8
)

老实说,文件大小可能足以满足我的需要,但为了安全起见,我正在寻找另一种检测唯一性的方法。

据我所知,唯一的选择是提取然后使用 file-hash 方法,但这比使用 ZipArchive [=25] 提供的东西要慢得多=].

在我的例子中,我有一个包含大约 230,000 张图像的目录,该目录由 30,000 个 zip 文件构建而成,每个 zip 文件中大约有 30 张图像,我想创建一个数据库,其中包含哪些图像来自哪个 zip,我知道会有很多重复项。

两个阶段的方法

CRC 是,as far as I can tell,一个 32 位无符号整数(4,294,967,295 个值)。对于较大的文件,如图像,我们可以假设它具有平坦的随机分布。我会将其与 size 结合起来以获得 希望独一无二的 字符串:

$stat = $zip->statIndex($index);
$str = $stat["crc"] . $stat["size"];

如果所有 ZIP 文件的压缩方法都相同,您可以添加压缩后的大小:

$stat = $zip->statIndex($index);
$str = $stat["crc"] . $stat["size"] . $stat["comp_size"];

这使得 极不可能 两个不同的图像产生相同的字符串,但就像真正的哈希一样,仍然有 一个非常小的变化 它将 return 两个不同图像的相同字符串

我认为这是不可接受的。

但是,如果两个图像 return 相同的字符串,您仍然可以更仔细地检查它们以检查它们是否确实相同。您可以从更好的 hashes 之一开始,但为什么不简单地进行 byte-by-byte 比较呢?通过这种方式,您实际上可以绝对确定您图像的独特性。

当然,这比仅仅依靠统计数据要慢,但我认为你必须同意这比错误识别图像的微小变化要好。

所以我的方法是先对 crcsize 进行粗略检查。如果这些相同,那么我实际上会比较这些文件以确保它们确实相同。这样我就不会 运行 改变假设两个图像是相同的,因为它们 crs/size 是相同的,但实际上它们并不相同。

不,32 位 CRC 太容易冲突了。考虑比较 CRC 和大小(最好还有压缩大小和压缩方法)——如果所有 4 个都相同,则可以安全地假设相同的文件。

不过,你对"duplicate"的定义是什么?

  • 两个图片文件可以具有相同的负载(实际照片)但元数据(标题、评论...)不同 - 在这种情况下,您需要自己对文件的部分进行哈希处理,因此元数据将被忽略。
  • 两个图片文件可以描绘同一场景,但具有不同的尺寸(即 800x600 与 1600x1200)或不同的压缩方式(有损、无损、隔行...)- 在这种情况下,您必须从视觉上解读它们。
  • 两个图片文件可以渲染相同的显示,但格式不同(即 PNG、TIFF、JPEG、WEBP...)- 在这种情况下,您需要比较它们的渲染位图。

如您所见:extracting/uncompressing这些文件将使您能够更精确地操作,首先使用您最喜欢的软件来检测重复项。