私の問題はzip圧縮です。ファイルをパーツに分割して並列に圧縮し、パーツを正しい順序で接続して、1 つのファイルで zip アーカイブとして保存する必要があります。ファイルを分割してパーツをホストに送信することは問題ではありません - 私は jpvm を使用しています。私の質問は次のとおりです。圧縮を分割する方法は? java.util.zip.Deflater を使用してすべての部分を圧縮し (結果はバイト配列)、それらを 1 つの ZipOutputStream に書き込もうとしましたが、これは機能しないようです - ファイルに保存する際に、既に圧縮されたバイトを圧縮しますもう一度。デフレーターですべての部分を圧縮してから、zip ヘッダー、チェックサムなどを手動で追加する必要がありますか? デフレーターはヘッダーを追加しますか? 助けていただければ幸いです、ありがとう!
2 に答える
nowrap
のオプションを使用Deflater
して、ヘッダーやトレーラーのない生の deflate ストリームを生成する必要があります。次に、その生の deflate ストリームを適切な zip ヘッダーとトレーラーでラップする必要があります。
複数のプロセッサで単一の deflate ストリームを作成するには、 zlibZ_SYNC_FLUSH
の操作を使用して、圧縮された出力をバイト境界 (最後のピースではないピース) にフラッシュできる必要があります。(最後のピースは正常に終了します。) その後、ピースを単純に連結できます。
Java 7 (Java 6 ではない)のドキュメントでは、メソッドのオプションの 4 番目のパラメーターでこれをサポートしていますdeflate()
。に設定できますSYNC_FLUSH
。
このようにデータを分割すると、各ブロックは前のブロックの履歴を利用できないため、圧縮率が低下します。これはメソッドを使用して解決できますsetDictionary()
。圧縮するデータと、その前にある 32K バイトの非圧縮データの両方を各スレッドに提供します。次に、32K を で使用しsetDictionary()
、その後にdeflate()
.
zlib を直接使用した C での並列圧縮の例については、pigzを参照してください。
deflate ストリームを取得したら、それを適切にラップして zip ファイルにします。zip ファイル形式については、アプリケーション ノートを参照してください。これらのフィールドに入力できるようにするには、圧縮されていないデータのCRC-32を計算する必要もあります。
残念ながら、あなたはあなたのコードを見せていないので、私はあなたのことを正確に理解しているとは確信できません. ただし、あなたの問題を理解している限り、次のことをお勧めします。
- 元のファイル サイズを確認し、チャンクのサイズを決定します。
- チャンク サイズに達するまで、ファイルの読み取りを開始します。を使用して内容を zip に書き込み
ZipOutputStream
ます。後でコンテンツに参加できるように、サフィックスを付けてファイルを作成します。接尾辞は実行中のインデックスである必要があります。1 つのファイルを複数の zip ファイルに保存する場合は、zip ごとに 1 つのエントリを使用します。 - zip ファイルを読み取るときは、接尾辞に従ってそれらを並べ替え (前述を参照)、唯一のエントリを読み取り、バイトを から にコピー
ZipInputSteam
しますFileOutputStream
。
残念ながら、複数のホストが何を意味するのか正確にはわかりませんでした。ファイルが大きすぎて、各zipを別々のマシンで同時に作成しているということですか? これが正しい場合は、#2 を次のように変更します。ファイル フラグメントの読み取り中に、そのコンテンツをリモート ホストに送信し、ZipOutputStream
そこで使用します。特定のポイントからファイルを読み取るには、 を使用しますInputStream.skip()
。