Golang 与 Python zlib:剖析输出差异
在提供的代码片段中,您尝试使用 Python 和 Python 来压缩字符串zlib 和 Go 的 flate 包。但是,您的 Python 实现产生的输出与 Go 对应的输出不同。为什么会这样?
为了辅助调试,我们来分析一下相关的代码片段:
Go 实现(compress.go)
<code class="go">package main import ( "compress/flate" "bytes" "fmt" ) func compress(source string) []byte { w, _ := flate.NewWriter(nil, 7) buf := new(bytes.Buffer) w.Reset(buf) w.Write([]byte(source)) w.Close() return buf.Bytes() } func main() { example := "foo" compressed := compress(example) fmt.Println(compressed) }</code>
Go 代码中的关键步骤是关闭 Writer,它会刷新压缩数据并将校验和写入末尾。
Python 实现 (compress.py)
<code class="python">from __future__ import print_function import zlib def compress(source): # golang zlib strips header + checksum compressor = zlib.compressobj(7, zlib.DEFLATED, -15) compressor.compress(source) # python zlib defaults to Z_FLUSH, but # https://golang.org/pkg/compress/flate/#Writer.Flush # says "Flush is equivalent to Z_SYNC_FLUSH" return compressor.flush(zlib.Z_SYNC_FLUSH) def main(): example = u"foo" compressed = compress(example) print(list(bytearray(compressed))) if __name__ == "__main__": main()</code>
这里,您已经通过调用compressor.flush(zlib.Z_SYNC_FLUSH)显式刷新了压缩器。
剖析输出
Python 输出包含第五个字节为 0,而 Go 为 4。前者是 Zlib 对数据结尾处理的结果。后者是由于 Flate 在关闭编写器时剥离了标头和校验和。
弥合输出差距
要从两个实现中获得可比较的输出,您可以:
在 Go 中使用 Flush(): 在 Go 代码中将 w.Close() 替换为 w.Flush() 以发出不带校验和的压缩数据。
<code class="go">buf := new(bytes.Buffer) w, _ := flate.NewWriter(buf, 7) w.Write([]byte(source)) w.Flush() return buf.Bytes()</code>
结论
虽然您可以调整参数以强制逐字节匹配在两种实现之间,这是没有必要的,甚至是不需要的。不同压缩库之间的输出兼容性有保证,但不完全相同。
以上是为什么 Python 和 Go zlib 对于相同的输入生成不同的压缩输出?的详细内容。更多信息请关注PHP中文网其他相关文章!