2012-12-17 33 views
0

我試圖解碼使用Python一個gzip Garmin的活動文件。根據Garmin,該文件是一個base64 gz文件。我通過上傳後從瀏覽器中的文件,並在Django應用程序接收數據。解碼的Base64 Gzip已在python

的文件的開頭是這樣的。

begin-base64 644 data.xml.gz\nH4sIAAAAAAAAA y9a4 lx3Hn d6fguB7JzNuGZkNigNfdrAGbMAYaXeNfbPolXplYiRSIFu

我用下面的代碼調整爲填充和解碼的base64:

import base64 
padding_factor = (4 - len(data) % 4) % 4 
data += "="*padding_factor 
data_decoded = base64.b64decode(unicode(data).translate(dict(zip(map(ord, u'-_'), u'+/')))) 

data_decoded的開頭是這樣的屏幕上:

\xe8"\x9f\xe6\xda\xb1\xee\xb8\xeb\x8e\x1dj\xd6\xb1\x9aX3\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03/Z\xe2\w\x1ewz~\x0b\x81\xec\x9c\xcd\xb8fd6(\r}\xda\xc0\x19\xb3\x00a\xa5\xde5\xf6\xcf\xa2U\xe9\x95\x88\x91H\x81n\xcb\xf7\xb4\x9f\xcc\xa7y%\xbd\x95\x9e\x13\xcd\x10\xf9Th\x04\x8d\xdf\xdf\xa6\xba\xa9\xcd\xf9=s\xf8G\xfc

print data_decoded樣子這樣的:

}???a??5?ϢU鎛?H?n????̧y%?????Th??ߦ????=s?G?

然後我嘗試使用解壓文件如下:

from cStringIO import StringIO 
from gzip import GzipFile 
sio = StringIO(data_decoded) 
gzf = gzip.GzipFile(fileobj=sio) 
guff = gzf.read() 

這之後,我得到以下錯誤:

File "<stdin>", line 1, in <module> 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/gzip.py", line 245, in read 
    self._read(readsize) 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/gzip.py", line 287, in _read 
    self._read_gzip_header() 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/gzip.py", line 181, in _read_gzip_header 
    raise IOError, 'Not a gzipped file' 
IOError: Not a gzipped file 

我也試過直接在命令將文件保存到磁盤並運行gunzip解並且這也會導致相同的錯誤。

任何幫助將不勝感激。

+1

gzip文件以字節0x1f和0x8b開頭,並且您顯示的data_decoded的開頭在開頭不包含該字符。你在那裏做了一些錯誤的事情,因爲簡單地做'\ nH4sIAAAAAAAAA y9a4 lx3Hnd6fguB7JzNuGZkNigNfdrAGbMAYaXeNfbPolXplYiRSIFu'.decode('base64')'給出了描述gzip所需的兩個初始字節。 – mmgp

回答

0

它看起來像你的解碼整個事情,包括begin-base64 644 data.xml.gz一部分,所以你得到了一堆在開始垃圾:

b1 = '''begin-base64 644 data.xml.gz\nH4sIAAAAAAAAA y9a4 lx3Hn 
d6fguB7JzNuGZkNigNfdrAGbMAYaXeNfbPolXplYiRSIFu''' 

b2 = '''\nH4sIAAAAAAAAA y9a4 lx3Hn 
d6fguB7JzNuGZkNigNfdrAGbMAYaXeNfbPolXplYiRSIFu''' 

如果您運行在B2算法,你得到的東西開始的:

​​

(我不知道你怎麼洛杉磯T IN複製和粘貼的m,但無論哪種方式,它不是有效的)

如果在b2運行它,你開始這樣的:。

\x1f\x8b\x08\x00\x00\x00 

這就是你想要的。

當然,起飛'\n'具有同樣的效果,因爲base64忽略空格。所以最有可能的是,它被用作分隔符。如果這實際上是'\\n'(又名r'\n')而不是'\n',那麼您的已將刪除以獲得正確答案。

而且,你似乎是做了很多額外的工作沒有很好的理由。數據很可能實際上是正確填充的,但這部分可能是值得的。但是整個translate(dict(zip(map(ord, u'-_'), u'+/')))與參數傳遞給b64decode的功能相同,但效率較低且難以閱讀(如果正確的話)。 (順便說一下,如果你在做translate作爲優化兩次調用replace的代價,Unicode和Unicode之間的轉換幾乎肯定會壓倒節省,即使你已經分析並確定它有所作爲, ð可能要產生translate地圖上方,既提高效率,所以你不要做一次每串,而且,更重要的是,爲便於閱讀)

將其組合在一起:

data = '''begin-base64 644 data.xml.gz\nH4sIAAAAAAAAA y9a4 lx3Hn 
d6fguB7JzNuGZkNigNfdrAGbMAYaXeNfbPolXplYiRSIFu''' 
_, data = data.split('\n', 1) 
padding_factor = (4 - len(data) % 4) % 4 
data += "="*padding_factor 
data_decoded = base64.b64decode(data, '-_') 

再次,如果您有'\\n'而不是'\n',請相應地更改split行。

+0

太棒了!非常感謝你的全面回答。 – user677325

+0

你說得對,填充是不必要的。一旦我分割數據,我剛剛使用base64.b64解碼(數據,' - _')。現在我明白了,在我解壓縮之前還需要通過StringIO來運行它嗎? – user677325

+0

@ user677325:如果你想通過'GzipFile'來完成,那麼是的,'StringIO'就是要走的路。另一種方法是解析或跳過頭部和'zlib.decompress'這個主體,但是你可能不想這樣做。 – abarnert

0

你需要,因爲它不是以base64數據的一部分,剝去文件的開頭。如果您知道\n將每個文件的一部分,你可以用它作爲分隔符:

index = data.find('\\n') 
if index > 0: 
    data = data[index+2:]