我正在編寫一個腳本,它將與來自儀器的數據一起作爲gzip流使用。在大約90%的情況下,gzip
模塊可以很好地工作,但其中一些流會導致產生IOError: Not a gzipped file
。如果gzip標題被刪除,deflate流直接送到zlib
,我改爲Error -3 while decompressing data: incorrect header check
。在將我的頭撞向牆壁大約半天之後,我發現有問題的流包含看似隨機數量的附加字節(不是gzip數據的一部分),並附加到最後。我如何使用包含額外數據的Gzip文件?
這令我奇怪的是,Python不能使用這些文件的原因有兩個:
- GZIP和7zip的能夠打開這些「填充」的文件沒有問題。 (Gzip已產生的消息
decompression OK, trailing garbage ignored
,7zip的成功默默) 無論是gzip和Python文檔似乎表明,這應該工作:(重點煤礦)
必須能夠到 無論壓縮數據的實際大小如何,都可以使用任何壓縮方法檢測壓縮數據的結尾,即 。 特別地, 解壓縮器必須能夠面向記錄的文件系統上的檢測和跳過所附 額外的數據爲有效的壓縮文件,或者當 的壓縮數據只能從一個裝置在一個 的倍數讀一定的塊大小。
調用
GzipFile
對象的close()
方法不會關閉FileObj文件,,因爲你可能希望壓縮數據後追加更多的材料。這也可以讓您將打開寫作StringIO
對象FileObj文件和檢索使用StringIO
對象的getvalue()
方法所產生的內存緩衝區。Python's
zlib.Decompress.unused_data
:包含過去壓縮的數據的末尾的字節的任何一個字符串。也就是說,這將保持
""
,直到包含壓縮數據的最後一個字節可用。 如果整個串變成了包含壓縮數據,這是""
,空字符串。的唯一方式來確定壓縮數據的字符串結尾是通過實際解壓縮它。這意味着,當壓縮數據包含在一個較大的文件的一部分,你只能通過讀取數據發現它的結束和餵養它其次是一些非空字符串爲減壓對象的
decompress()
方法,直到unused_data
屬性不再空的字符串。
這裏是我試過的四種方法。 (這些例子是Python 3.1,但我測試過2.5和2.7,並且有同樣的問題。)
# approach 1 - gzip.open
with gzip.open(filename) as datafile:
data = datafile.read()
# approach 2 - gzip.GzipFile
with open(filename, "rb") as gzipfile:
with gzip.GzipFile(fileobj=gzipfile) as datafile:
data = datafile.read()
# approach 3 - zlib.decompress
with open(filename, "rb") as gzipfile:
data = zlib.decompress(gzipfile.read()[10:])
# approach 4 - zlib.decompressobj
with open(filename, "rb") as gzipfile:
decompressor = zlib.decompressobj()
data = decompressor.decompress(gzipfile.read()[10:])
我做錯了什麼?
UPDATE
好,同時與gzip
的問題似乎是在模塊中的一個錯誤,我zlib
問題是自己造成的。 ;-)
在挖掘到gzip.py
時我意識到我在做什麼錯了 - 默認情況下,zlib.decompress
等。期望zlib-wrapped流,而不是裸露的縮小流。通過傳入負值wbits
,您可以告知zlib
跳過zlib標題並對原始流進行解壓縮。這兩個工作:
# approach 5 - zlib.decompress with negative wbits
with open(filename, "rb") as gzipfile:
data = zlib.decompress(gzipfile.read()[10:], -zlib.MAX_WBITS)
# approach 6 - zlib.decompressobj with negative wbits
with open(filename, "rb") as gzipfile:
decompressor = zlib.decompressobj(-zlib.MAX_WBITS)
data = decompressor.decompress(gzipfile.read()[10:])
其實我搞亂大約有`gzip`的內部位在調試的問題,但它沒有發生,我來解決那裏的問題並用我的腳本打包修改後的模塊。這真是醜陋,但聽起來它可能仍然是最好的選擇。 : -/ – 2011-02-08 01:29:56
@Ben:它是獨立的,至少它不是一項重大成本;只有一個文件。本地模塊更令人討厭。 – 2011-02-08 01:34:11