压缩输出不同于 Go to Ruby 实现

Compressed output differs from Go to Ruby Implementation

我正在实施一个程序,将文件缩小为 git blob 并适当地存储它。

我有一个ruby reference implementation that's based on an article from the git book

我正在尝试在 go 中实现这个 here

但是,我 运行 遇到了一个问题,即存储的压缩数据与每个实现略有不同。

vbindiff 表明前 2 个字节相同(如 运行 来自 this test script) (If I'm reading this right). These bytes store the compression method and flags, and flags respectively (as per https://www.rfc-editor.org/rfc/rfc1950)。第三个字节是差异开始的地方,这是字典 ID 或原始输入数据的开始。数据保持相似,直到接近文件末尾。我假设这可能是 ADLER32 校验和的差异。

默认情况下,zlib 的 go 和 Ruby 实现似乎都没有将字典传递给 zlib(根据 go zlib source and ruby zlib source

数据看起来完全相同。

我不确定库中是否存在实施错误,或者我是否遗漏了什么。

为什么这些输出不同?

RFC 1951 中定义的 deflate 算法(用于 RFC 1950 定义的 zlib 格式以及 RFC 1952 定义的 gzip 中)允许实现中的变化,这可能会在压缩时导致不同的结果。但是这些结果仍然会解压缩到相同的值。这允许在压缩时间和压缩级别之间进行权衡,并且也使得像 zopfli 这样的程序可以实现比原始 zlib 库更好的压缩(以显着增加压缩时间为代价)。

Go 使用自己的用 Go 编写的 deflate 算法实现,而 ruby 使用 zlib library。这就是您的示例在同一输入上创建不同压缩输出的原因。但是,如果您从 Go 或 Ruby 程序中获取输出并解压缩(无论是否使用 Ruby 或 Go 或任何符合标准的实现),它都会再次产生完全相同的值。