2014-03-26 37 views
0

我需要從通常使用gzip壓縮的一些文件中讀取二進制數據。我已成功使用的gzip模塊讀取數據:Python:從文件中讀取數據有時會被壓縮,有時候不會

def decode(self, filename): 
    with gzip.open(filename, 'rb') as f: 
     # ReadData 

但是有時文件沒有壓縮在這種情況下,我得到一個IOError(因爲文件沒有gzip頭)。

我可以這樣做:

try: 
    f = gzip.open(filename, 'rb') 
    f._read_gzip_header() 
    f.rewind() 
except IOError: 
    f.close() 
    f = open(filename, 'rb') 

with f as gz: 
    #ReadData 

,但我不覺得這是解決它的好方法。

我正在尋找一個優雅的解決方案來解決這個問題。我將爲幾種文件類型編寫幾個「解碼」函數。我考慮的解決方案是創建一個GzipFile的子類來處理它,但我相信可能有更好的方法。

我使用Python 2.7

預先感謝您的任何建議!

+1

您的解決方案有什麼問題?我不會關閉文件,然後立即重新打開它,但用try/except處理潛在的IOError是完全正確的。只是嘗試讀取它作爲gzip,除了'IOError'讀作純文本,除了'IOError'回溯。然後乾淨地處理所有的處理,處理代碼不知道文件是如何打開的。 –

+0

那麼,我的解決方案可能沒有什麼問題(我對Python的經驗並不豐富,有時候我懷疑什麼是好的/錯誤的)。我不喜歡我的解決方案的原因是我至少會編寫6個解碼函數(針對6種不同的文件類型),我認爲可能有更好的方法可以避免在每個函數中寫入try-except塊。但感謝您的評論。 – user3466240

+0

如果問題是您不想複製代碼,那麼只需創建一個新的上下文管理器,無論輸入是否壓縮,都會生成一個具有未壓縮數據的文件類對象。下面是一個[上下文管理器'named_pipe()'的代碼示例,它封裝了創建命名管道](http://stackoverflow.com/a/22435492/4279) – jfs

回答

1

可以檢查頭兩個字節是\x1f\x8b,按照RFC 1952

會員首部和尾部

ID1(識別1)ID2(識別2) 這些具有固定值ID1 = 31(0x1f,\ 037),ID2 = 139(0x8b,\ 213),以標識文件爲gzip格式。

因此,例如,

with open('test.gz','rb') as f: 
    print(f.read(2)) 

b'\x1f\x8b' #well, that was gzipped 

with open('test','rb') as f: 
    print(f.read(2)) 

b'he' #must not be gzipped 

想必你會做一些控制流程基於這兩個字節,則f.seek(0)並進行相應處理。

但說實話?您的解決方案很好(以不必要的關閉/重新打開部分爲模)。 try/except是pythonic。

+0

感謝您的回答。 (我對兩位煉金術士的評論也適用於此)。但我不明白我的代碼的哪一部分是不必要的:如果我不使用「with」語句打開文件,是否需要使用close()? – user3466240

+0

是的,如果不使用with語句作爲上下文管理器,應該嘗試手動顯式關閉文件對象。但是,寫'f。關閉「,然後」打開(same_file)「與關閉然後重新打開即將退出的門無關。 :P –

相關問題