1

圧縮された XML の複数の個別のストリームを含む zip ファイルが提供されました。圧縮ファイルは 833 MB です。

1 つのオブジェクトとして解凍しようとすると、最初のストリーム (約 19 kb) しか得られません。

古い質問への回答として提供された次のコードを変更して、各ストリームを解凍し、ファイルに書き込みました。

import zlib

outfile = open('output.xml', 'w')

def zipstreams(filename):
    """Return all zip streams and their positions in file."""
    with open(filename, 'rb') as fh:
        data = fh.read()
    i = 0
    print "got it"
    while i < len(data):
        try:
            zo = zlib.decompressobj()
            dat =zo.decompress(data[i:])
            outfile.write(dat)
            zo.flush()
            i += len(data[i:]) - len(zo.unused_data)
        except zlib.error:
            i += 1
    outfile.close()

zipstreams('payload')
infile.close()

このコードが実行され、目的の結果が生成されます (すべての XML データが 1 つのファイルに解凍されます)。問題は、作業に数日かかることです!

圧縮ファイルには何万ものストリームが含まれていますが、これははるかに高速なプロセスであるように思われます。833MB (推定 3GB raw) を解凍するのにおよそ 8 日かかります。

これをより効率的に行う別の方法はありますか、それとも速度が遅いのは、私が立ち往生している読み取り-解凍-書き込み---繰り返しのボトルネックの結果ですか?

あなたが持っているポインタや提案をありがとう!

4

3 に答える 3

1

833 MB の解凍には、最新のプロセッサ (2 GHz i7 など) で約 30 秒かかります。そうです、あなたは何か非常に間違ったことをしています。すべてではありませんが、エラーが発生するかどうかを確認するためにすべてのバイト オフセットで解凍を試みることも問題の一部です。圧縮されたデータを見つけるためのより良い方法があります。理想的には、フォーマットを見つけるか把握する必要があります。または、 RFC 1950 仕様を使用して有効な zlib ヘッダーを検索することもできますが、誤検知が発生する可能性があります。

さらに重要なのは、一度に 833 MB 全体をメモリに読み込み、3 GB をメモリに解凍することです。あなたのマシンにはどのくらいのメモリがありますか? 仮想メモリにスラッシングしている可能性があります。

表示されたコードが機能する場合、データは圧縮されていません。zip は特定のファイル形式で、通常は .zip 拡張子が付いており、ファイル システム内のディレクトリを再構築することを目的とした、ローカルおよび中央のディレクトリ情報の構造内に生の圧縮データをカプセル化します。コードが zlib ストリームを探しており、明らかに見つけているため、かなり異なるものが必要です。あなたが持っているフォーマットは何ですか?どこで手に入れましたか?それはどのように文書化されていますか?たとえば、最初の 100 バイトのダンプを提供できますか?

これを行う方法は、すべてをメモリに読み込み、ストリーム全体を一度にメモリに解凍することではありません。代わりにzlib.decompressobj、一度に 1 つずつ提供できるインターフェースを使用して、結果として利用可能な解凍されたデータを取得してください。入力ファイルをはるかに小さな断片で読み取り、文書化された形式を使用するか、zlib (RFC 1950 ヘッダー) を探して解凍されたデータ ストリームを見つけ、解凍されたオブジェクトを介して一度にチャンクを実行し、解凍されたデータを書き出すことができます。あなたがそれをしたいところ。 decomp.unused_data圧縮ストリームの終わりを検出するために使用できます(あなたが見つけた例のように)。

于 2013-05-12T16:47:21.833 に答える
0

コメントに記載されている内容からすると、個別に送信されたはずの個々のファイルを連結しているように思えます。つまり、それぞれにスキップする必要がある 32 バイトのヘッダーがあります。

これらのヘッダーをスキップしない場合、おそらく説明したとおりの動作になります。運が良ければ、32 個の無効なヘッダー エラーが発生し、次のストリームを正常に解析できます。運が悪ければ、32 バイトのガベージが実際のストリームの始まりのように見え、最終的にデコード エラーが発生するまで、任意の数のバイトを解析するために多くの時間を浪費することになります。(本当に運が悪いと、実際にはデコードに成功し、巨大なゴミの塊ができて、1 つまたは複数の後続のストリームを使い果たしてしまいます。)

したがって、各ストリームが終了した後、32 バイトだけスキップしてみてください。

または、次のストリームの開始を検出するより信頼できる方法がある場合 (これが、オフセットを出力して 16 進エディターでデータを確認するように指示した理由です。alexis は zlib 仕様を確認するように指示しましたが、 )、代わりにそれを行います。

于 2013-05-12T13:18:28.950 に答える