调试Python的zlib和golang的zlib之间的区别。以下为什么不具有相同的结果?golang/python 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
- 是什么导致不同的输出?
zlib使用DEFLATE实现,但flate和zlib不一样。在这里,你正在关闭flate流,而在python中,你只是在冲洗。如果将Go代码更改为'Flush()',则输出将相同。还要注意不同的实现不能保证产生相同的二进制输出,它们只能保证产生兼容的输出。 – JimB
@ jimb:https://golang.org/pkg/compress/flate/说:“Package flate实现了RFC 1951中描述的DEFLATE压缩数据格式...”,这似乎与第一句相矛盾,或者我误解了你(或docs =))。同样,https://golang.org/pkg/compress/flate/#Writer.Close声明刷新作者并在'w.Write(...)'行添加一个明确的'w.Flush()'后添加更多的填充/校验和字节。你介意提供一些更详细的信息,因为我明显没有遵循这些内容。 – everial
该输出与python输出相匹配:https://play.golang.org/p/_SCAspI3Mq。我不明白你发现什么矛盾;你在python中使用zlib,它在内部使用DEFLATE来产生一个zlib格式的输出,而你的Go例子直接使用DEFLATE实现。我不知道是否可以让python zlib库输出原始完整的DEFLATE流,但是试图让不同的库输出压缩数据的逐字节匹配似乎不是有用或可维护的。 – JimB