golang/python zlib 差异

golang/python zlib difference

调试 Python 的 zlib 和 golang 的 zlib 之间的差异。为什么以下结果不同?

compress.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)
}

compress.py:

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()

结果

$ go version
go version go1.7.3 darwin/amd64
$ go build compress.go
$ ./compress
[74 203 207 7 4 0 0 255 255]
$ python --version
$ python 2.7.12
$ python compress.py
[74, 203, 207, 7, 0, 0, 0, 255, 255]

Python 版本的第五个字节为 0,但 golang 版本有 4 -- 是什么导致了不同的输出?

python 示例的输出不是 "complete" 流,它只是在压缩第一个字符串后刷新缓冲区。您可以通过将 Close() 替换为 Flush():

从 Go 代码获得相同的输出

https://play.golang.org/p/BMcjTln-ej

func compress(source string) []byte {
    buf := new(bytes.Buffer)
    w, _ := flate.NewWriter(buf, 7)
    w.Write([]byte(source))
    w.Flush()

    return buf.Bytes()
}

但是,您比较的是 python 中 zlib 的输出,它在内部使用 DEFLATE 生成 zlib 格式输出,而 Go 中的 flate[=22] =] DEFLATE 实现。我不知道您是否可以获得 python zlib 库来输出原始的、完整的 DEFLATE 流,但是尝试让不同的库来输出压缩数据的逐字节匹配似乎没有用或可维护.压缩库的输出只能保证兼容,不能完全相同。