英文:
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
- 是什么导致了不同的输出?
英文:
Debugging differences between Python's zlib and golang's zlib. Why don't the following have the same results?
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()
Results
$ 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]
The Python version has 0
for the fifth byte, but the golang version has 4
-- what's causing the different output?
答案1
得分: 4
Python示例的输出不是一个“完整”的流,它只是在压缩第一个字符串后刷新缓冲区。你可以通过将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中使用DEFLATE内部产生zlib格式输出的zlib库的输出,和Go中使用的flate
库,它是一个DEFLATE实现。我不知道你是否可以让Python的zlib库输出原始的、完整的DEFLATE流,但是试图让不同的库输出逐字节匹配的压缩数据似乎没有用处,也不易于维护。压缩库的输出只保证是兼容的,而不是完全相同的。
英文:
The output from the python example isn't a "complete" stream, its just flushing the buffer after compressing the first string. You can get the same output from the Go code by replacing Close()
with Flush()
:
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()
}
However, you are comparing output from zlib in python, which uses DEFLATE internally to produce a zlib format output, and flate
in Go, which is a DEFLATE implementation. I don't know if you can get the python zlib library to output the raw, complete DEFLATE stream, but trying to get different libraries to output byte-for-byte matches of compressed data doesn't seem useful or maintainable. The output of the compression libraries is only guaranteed to be compatible, not identical.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论