0

Python を使用して gzip ガーミン アクティビティ ファイルをデコードしようとしています。Garmin によると、ファイルは base64 gz ファイルです。私は投稿を介してブラウザからファイルをアップロードし、Django アプリでデータを受信して​​います。

ファイルの先頭はこんな感じ。

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 を実行しようとしましたが、これも同じエラーが発生します。

どんな助けでも大歓迎です。

4

2 に答える 2

0

一部を含む全体をデコードしているように見えるbegin-base64 644 data.xml.gzため、最初に大量のゴミが得られます。

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

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

b2 でアルゴリズムを実行すると、次のような結果が得られます。

m\xe8"\x9d\xb6\xac{\xae

(コピーと貼り付けで を紛失した方法はわかりませんmが、どちらにしても有効ではありません。)

で実行するとb2、次のようなものが得られます。

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

それがあなたが望むものです。

もちろん'\n'、base64 は空白を無視するため、 を削除しても同じ効果があります。そのため、区切り文字として使用されている可能性が最も高いです。それが実際にはではなく'\\n'(aka r'\n') である'\n'場合、正しい答えを得るためにそれを削除する必要があります。

また、正当な理由もなく多くの余分な作業を行っているようです。ほとんどの場合、データは実際には正しくパディングされていますが、その部分は価値があるかもしれません。しかし、全体は に引数をtranslate(dict(zip(map(ord, u'-_'), u'+/')))渡すのと同じことを行いますが、効率が悪く、読みにくくなります (正しい場合)。(ちなみに、 2 回呼び出すコストに対する最適化を行っていた場合、Unicode への変換と Unicode からの変換が節約を圧倒することはほぼ確実です。上記のマップを生成したいのですが、どちらも効率のためであり、文字列ごとに 1 回実行する必要はありません。さらに重要なのは、読みやすさのためです)。altcharsb64decodetranslatereplacetranslate

それを一緒に入れて:

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, '-_')

繰り返しますが、 a'\\n'ではなく aがある場合は、それに応じ'\n'て行を変更してくださいsplit

于 2012-12-17T21:19:55.047 に答える
0

base64 データの一部ではないため、ファイルの先頭を削除する必要があります。がすべてのファイルの一部になることがわかっている場合は、\nそれを区切り文字として使用できます。

index = data.find('\\n')
if index > 0:
    data = data[index+2:]
于 2012-12-17T21:17:56.760 に答える