2017-07-28 3 views
1

プロジェクトでは、大量の暗号化されたデータが大量に読み込まれて読み込まれます。復号化には膨らませるよりもずっと時間がかかるので、私は暗号化して保存する前にデータを収縮させたいと思っています。データを固定長バッファに収めます。

私が直面している問題は、データが固定長のチャンクまたはページに格納されていることです。ディスク上のこれらのチャンクは、ページの高速検索のために固定長のままにする必要があります。だから基本的に私は固定サイズのページにできるだけ多くのデータを収縮しようとしています。

現在、私はそうするための良いアプローチを見つけようとしています。しかし、現時点では、データが追加され、圧縮されていないサイズがページの限界に近くなるたびに、圧縮されたサイズの後ろに少し立ち往生しています。 (なぜなら、理論上、データのエントロピーが非常に高い場合、データは圧縮のために少し成長する可能性があるからです)。現在、私は次のようなアプローチをしようとしている:

final Deflater deflater = new Deflater();//Deflater.HUFFMAN_ONLY); 
    final Inflater inflater = new Inflater(); 

    long start; 
    long duration; 
    int freeSpace = size; 
    int fill = 0; 
    byte[] page; 
    final byte[] buf = new byte[8]; 

    deflater.reset(); 
    try(ByteArrayOutputStream boas = new ByteArrayOutputStream(size); 
      DeflaterOutputStream dos = new DeflaterOutputStream(boas, deflater, size, true)){ 
     start = System.currentTimeMillis(); 
     while(true){ 
      long compressable = (long) (Random.nextLong(30) + 100); 

      fill += ByteTools.longToByteArray(compressable, buf, 0, 8); 
      dos.write(buf); 
      freeSpace = size - boas.size(); 

      if(freeSpace < 16){ 
       System.out.println(boas.size()); 
       dos.finish(); 
       System.out.println(boas.size()); 
       page = boas.toByteArray(); 
       break; 
      } 
     } 
     duration = System.currentTimeMillis() - start; 
    } 

上記のコードは、収縮させるための機能で、出力の一方長)(dos.finished時に劇的に増加しています。これは驚くべきことではありませんが、結果の出力サイズを判断する良い方法があるのですか、タスクに適した他の圧縮方式がありますか?

パディングを適用することができるので、100%正確な出力サイズは必要ありません。95%〜100%の範囲は完全であり、十分に機能します。もちろん、100%+は常に防止する必要があります。

トレイルとエラーに基づいて、私は良い結果を与えるビットをルーチンに適応させました。しかし、私はまだこの解決策に慣れていません。

 while(true){ 
      long compressable = (long) (Random.nextLong(30) + 100); 

      block += ByteTools.longToByteArray(compressable, buf, 0, 8); 
      dos.write(buf); 

      if(block >= check){ 
       //check /= 2; 
       dos.flush(); 
       fill += block; 
       block = 0; 
       check = (size - boas.size()) - 8; 
       System.out.println(check); 
      } 

      if(check < 16){ 
       fill += block; 
       dos.finish(); 
       page = boas.toByteArray(); 
       break; 
      } 
     } 

溶液(1つのブロック)オリジナルcomression比から遠くない圧縮比を有し、必要な出力サイズの8つのバイト内に留まります。小切手サイズの減少は次の形式をとります。

16384 
8088 
4259 
2207 
1110 
540 
246 
94 
32 
3 

ページ生成中に9回のフラッシュと1回の終了が発生します。

答えて

1

deflateはこれにはあまり適していませんが、ブロックを数回試してみると、ブロックを埋めるように強制することができます。 fitblkを見てください。これはあなたが求めていることを正確に行い、3つの圧縮パスを実行し、その間に2つの圧縮解除を含めます。

あなたのブロックサイズを超えて圧縮し、ブロックサイズだけを解凍し、解凍したものだけを再圧縮することです。あなたはそれを非常に近くにするために2回、あるいは多くの時間、正確にブロックを満たします。

+0

これは、充填されたブロックサイズ以上に何が圧縮されるのかを知るために圧縮率についていくらか推測する必要があります。しかし、それは私に非常に良いヒント、すなわち部分的減圧を使用することを与える。私のシナリオでは、 "unpaged"であるファイルの "末尾"にバッファを使用し、バッファがページサイズを超えるたびにページングすることができます。私はそれがシナリオに合っているかどうかを見るためにいくつかのテストを書きます。ありがとう。 –

+0

推測は必要ありません。最初のパスについては、ブロックをいっぱいにするまで圧縮を続けてください。 –

+0

Javaでは、ComressorをOutputStreamとともに使用すると、出力サイズはフラッシュするまで更新されません。限り、私はフラッシュが圧縮サイクルを引き起こすことを理解しているので、あまりにも頻繁にフラッシュを呼び出すのを防ぐために、私は見積もりが必要です。 –

関連する問題