68

これは前の質問に似ていますが、そこにある回答は私のニーズを満たしていないため、私の質問は少し異なります。

私は現在、ソートされたデータを含むいくつかの非常に大きなファイルに gzip 圧縮を使用しています。ファイルが圧縮されていない場合、バイナリ検索は、並べ替えられたデータ内の場所へのシークをサポートする便利で効率的な方法です。

しかし、ファイルが圧縮されると、事態は複雑になります。最近、 zlibのオプションについて知りましたZ_FULL_FLUSH。これは、圧縮中に使用して、圧縮された出力に「同期ポイント」を挿入inflateSync()できます(その後、ファイル内のさまざまなポイントから読み取りを開始できます)。これは問題ありませんが、この機能を追加するには、既に持っているファイルを再圧縮する必要があります (奇妙なことにgzip、このオプションはありませんが、必要に応じて独自の圧縮プログラムを作成します)。

ある情報源によると、完全な解決策ではないようZ_FULL_FLUSHです...すべての gzip アーカイブでサポートされているわけではないだけでなく、アーカイブ内の同期ポイントを検出するというアイデア自体が誤検知を引き起こす可能性があります (同期のマジック ナンバーとの一致による)ポイント、またはZ_SYNC_FLUSHも同期ポイントを生成しますが、ランダム アクセスには使用できないため)。

より良い解決策はありますか?可能であれば、インデックス作成用の補助ファイルを使用することは避けたいと思います。また、準ランダム アクセスの明示的なデフォルト サポートが役立ちます (10 MB 間隔ごとに読み取りを開始できるように、粒度が大きい場合でも)。gzip よりもランダムな読み取りをより適切にサポートする別の圧縮形式はありますか?

編集: 前述したように、圧縮データでバイナリ検索を実行したいと考えています。特定の (圧縮されていない) 位置をシークする必要はありません。圧縮ファイル内の粗い粒度でシークするだけです。「この圧縮ファイルの約 50% (25%、12.5% など) からデータを解凍する」などのサポートが必要です。

4

13 に答える 13

35

dictzipを見てください。gzip と互換性があり、粗いランダム アクセスが可能です。

そのマニュアルページからの抜粋:

dictzipは、gzip ファイル形式と完全に互換性のある方法でgzip (1) アルゴリズム (LZ77)を使用してファイルを圧縮します。gzip ファイル形式 (RFC 1952 の 2.3.1.1 で説明されている追加フィールド) の拡張により、圧縮ファイルのヘッダーに追加データを格納できます。gzip や zcat などのプログラムは、この余分なデータを無視します。ただし、[dictzcat --start] はこのデータを使用して、ファイルに対して疑似ランダム アクセスを実行します。

Ubuntuにパッケージdictzipがあります。または、そのソース コードはdictd-*.tar.gzにあります。そのライセンスは GPL です。自由に勉強してください。

アップデート:

dictzip を改善して、ファイル サイズの制限をなくしました。 私の実装は MIT ライセンスの下にあります。

于 2010-10-24T19:48:35.027 に答える
20

圧縮されていないデータの特定の場所へのランダム アクセスをサポートする圧縮ファイル形式は知りませんが (マルチメディア形式を除く)、独自の形式を作成することはできます。

たとえば、bzip2 圧縮ファイルは、圧縮されていないサイズが 1MB 未満の独立した圧縮ブロックで構成されており、これらは一連のマジック バイトで区切られているため、bzip2 ファイルを解析し、ブロック境界を取得してから、適切なブロックを解凍することができます。これには、ブロックの開始位置を覚えておくためのインデックスが必要です。

それでも、最善の解決策は、ファイルを選択したチャンクに分割し、アーカイブ内の個々のファイルへのランダム アクセスをサポートする zip や rar などのアーカイバで圧縮することだと思います。

于 2009-01-09T23:19:55.317 に答える
10

.xzファイル形式(LZMA 圧縮を使用) はこれをサポートしているようです:

ランダム アクセス読み取り: データは個別に圧縮されたブロックに分割できます。すべての .xz ファイルにはブロックのインデックスが含まれているため、ブロック サイズが十分に小さい場合は、制限付きのランダム アクセス読み取りが可能になります。

目的にはこれで十分です。欠点は、liblzma の API (これらのコンテナーと対話するため) が十分に文書化されていないように見えるため、ブロックにランダムにアクセスする方法を理解するのに多少の労力がかかる場合があることです。

于 2014-05-03T11:53:47.397 に答える
7

gzip および bzip2 アーカイブへのランダム アクセスを提供するソリューションが存在します。

( 7zip の何かを探しています)

于 2010-12-17T01:42:32.667 に答える
3

ロスレス圧縮は、一部の領域では他の領域よりもうまく機能するため、圧縮データを便利な長さ BLOCKSIZE のブロックに格納すると、各ブロックの圧縮バイト数がまったく同じであっても、一部の圧縮ブロックは他のブロックよりもはるかに長い平文に展開されます。 .

「Compression: A Key for Next-Generation Text Retrieval Systems」(Nivio Ziviani、Edleno Silva de Moura、Gonzalo Navarro、Ricardo Baeza-Yates 共著、 Computer Magazine November 2000 http://doi.ieeecomputersociety.org/10.1109 ) を参照してください。 /2.881693

彼らの圧縮解除プログラムは、1、2、または 3 バイトの圧縮データを受け取り、(語彙リストを使用して) 単語全体に圧縮解除します。圧縮されたテキストで単語やフレーズを直接検索できます。これは、圧縮されていないテキストを検索するよりも高速です。

彼らのデコンプレッサを使用すると、テキスト内の任意の単語を通常の (バイト) ポインターでポイントし、そのポイントからすぐに解凍を開始できます。

テキスト内の一意の単語はおそらく 65,000 未満であるため、すべての単語に一意の 2 バイト コードを与えることができます。(KJV 聖書には約 13,000 の固有の単語があります)。65,000 を超える単語がある場合でも、最初の 256 の 2 バイト コード「単語」を可能なすべてのバイトに割り当てるのは非常に簡単です。単語とフレーズ」。(頻繁に使用される単語やフレーズを 2 バイトに圧縮することで得られる圧縮は、通常、1 文字あたり 2 バイトを使用して単語をときどきスペルアウトする「拡張」の価値があります)。適切な圧縮を行う「頻繁に使用する語句」のレキシコンを選択するには、さまざまな方法があります。たとえば、LZW コンプレッサーを微調整して「フレーズ」をダンプできます。レキシコン ファイルに対して、フレーズごとに 1 行を複数回使用し、すべてのデータに対して実行します。または、圧縮されていないデータをレキシコン ファイル内の 5 バイトのフレーズに、フレーズごとに 1 行ずつ任意に切り刻むこともできます。または、圧縮されていないデータを実際の英単語に分割し、各単語 (単語の先頭のスペースを含む) をレキシコン ファイルに入れることもできます。次に、「sort --unique」を使用して、そのレキシコン ファイル内の重複する単語を削除します。(完璧な「最適な」レキシコンのワードリストを選択することは、まだ NP 困難と見なされていますか?) そして、各単語 (単語の先頭のスペースを含む) をレキシコン ファイルに入れます。次に、「sort --unique」を使用して、そのレキシコン ファイル内の重複する単語を削除します。(完璧な「最適な」レキシコンのワードリストを選択することは、まだ NP 困難と見なされていますか?) そして、各単語 (単語の先頭のスペースを含む) をレキシコン ファイルに入れます。次に、「sort --unique」を使用して、そのレキシコン ファイル内の重複する単語を削除します。(完璧な「最適な」レキシコンのワードリストを選択することは、まだ NP 困難と見なされていますか?)

巨大な圧縮ファイルの先頭にレキシコンを保存し、便利な BLOCKSIZE までパディングしてから、圧縮テキスト (一連の 2 バイトの「単語」) をそこからファイルの最後まで保存します。おそらく、サーチャーはこのレキシコンを 1 回読み取り、解凍中に RAM にデコードしやすい形式で保持し、「2 バイト コード」から「可変長フレーズ」への解凍を高速化します。私の最初のドラフトは、フレーズ リストごとに 1 行の単純なものから始めますが、後で何らかのインクリメンタル コーディングまたは zlib を使用して、より圧縮された形式でレキシコンを保存するように切り替えることができます。

圧縮されたテキストに任意のランダムな偶数バイト オフセットを選択し、そこから解凍を開始できます。よりきめ細かいランダム アクセス圧縮ファイル フォーマットを作成することは不可能だと思います。

于 2010-08-07T20:52:23.410 に答える
3

これがあなたの正確な状況で実用的かどうかはわかりませんが、大きなファイルをそれぞれ 10 MB などの小さなファイルに gzip することはできませんか? file0.gz、file1.gz、file2.gz などの一連のファイルが作成されます。元のラージ内の特定のオフセットに基づいて、"file" + (offset / 10485760) + ".gz". 圧縮されていないアーカイブ内のオフセットはoffset % 10485760.

于 2009-01-09T22:41:07.283 に答える
3

考えられる解決策は次の 2 つです。

  1. OSに圧縮を処理させ、すべてのテキストファイルを含む圧縮ファイルシステム(SquashFS、clifs、cloop、cramfs、e2comprなど)を作成してマウントし、アプリケーションプログラムで圧縮について何もしません。

  2. ファイルシステム イメージを圧縮する代わりに、各テキスト ファイルで直接 clifs を使用します (テキスト ファイルごとに 1 つの clufs)。「mkclicfs mytextfile mycompressedfile」を「gzip <mytextfile >mycompressedfile」および「clicfs mycompressedfile directory」と考えて、ファイル「directory/mytextfile」を介してデータへのランダム アクセスを取得します。

于 2012-02-10T16:52:46.720 に答える
0

私は、特定の種類の生物学的データを圧縮するためのオープンソースツールの著者です。と呼ばれるこのツールはstarch、データを染色体ごとに分割し、それらの分割をインデックスとして使用して、より大きなアーカイブ内の圧縮データユニットに高速アクセスします。

染色体ごとのデータは、ゲノム座標の冗長性を取り除くために変換され、変換されたデータは、bzip2またはgzipアルゴリズムのいずれかで圧縮されます。オフセット、メタデータ、および圧縮されたゲノムデータは1つのファイルに連結されます。

ソースコードは、GitHubサイトから入手できます。LinuxとMacOSXでコンパイルしました。

あなたの場合、カスタムアーカイブ形式のヘッダーにオフセット(10 MBなど)を保存できます。ヘッダーを解析し、オフセットを取得しfseekて、ファイルをcurrent_offset_sum+ずつ増分しますheader_size

于 2011-10-26T21:02:04.010 に答える
0

razip は、このサポートのために微調整する必要がある gzip/bzip2 よりも優れたパフォーマンスでランダム アクセスをサポートします - 「OK」ランダム アクセスを犠牲にして圧縮を減らします。

http://sourceforge.net/projects/razip/

于 2011-08-23T15:07:36.277 に答える