2016-11-30 45 views
4

調試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 - 是什麼導致不同的輸出?

+0

zlib使用DEFLATE實現,但flate和zlib不一樣。在這裏,你正在關閉flate流,而在python中,你只是在沖洗。如果將Go代碼更改爲'Flush()',則輸出將相同。還要注意不同的實現不能保證產生相同的二進制輸出,它們只能保證產生兼容的輸出。 – JimB

+0

@ 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

+1

該輸出與python輸出相匹配:https://play.golang.org/p/_SCAspI3Mq。我不明白你發現什麼矛盾;你在python中使用zlib,它在內部使用DEFLATE來產生一個zlib格式的輸出,而你的Go例子直接使用DEFLATE實現。我不知道是否可以讓python zlib庫輸出原始完整的DEFLATE流,但是試圖讓不同的庫輸出壓縮數據的逐字節匹配似乎不是有用或可維護的。 – JimB

回答

1

python示例的輸出不是一個「完整」流,它只是在壓縮第一個字符串之後刷新緩衝區。您可以通過使用Flush()更換Close()得到的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() 
} 

但是,你比較從zlib的Python中,它使用內部DEFLATE產生的zlib格式輸出輸出,和flate在Go中,其中的DEFLATE實現。我不知道是否可以讓python zlib庫輸出原始完整的DEFLATE流,但是試圖讓不同的庫輸出壓縮數據的逐字節匹配似乎不是有用或可維護的。壓縮庫的輸出只能保證兼容,不完全相同。

+0

哎呀,對不起,我花了這麼長時間才接受答案,錯過了通知。感謝您將它寫得很好。 =) – everial