对于一个项目,我使用大量的加密数据来处理大量的读取数据。由于解密需要比膨胀更长的时间,所以我愿意在加密和存储之前压缩数据。将数据放入一个固定长度的缓冲区中
我面临的困难是数据存储在固定长度的块或页面中。磁盘上的这些块需要保持固定长度以便快速查找页面。所以基本上我试图尽可能多地将数据泄漏到固定大小的页面中。
在目前我试图找到一个很好的方法来做到这一点。然而,在这一刻,我有点卡住每次添加数据后压缩的大小和未压缩的大小接近页面限制。 (因为如果数据的熵很高,数据在理论上可能由于压缩而增长一点)。目前,我试图以下方法:
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;
}
}
的解决方案具有的压缩率是不远处的原始comression比率(在一个块)和8个字节所需的输出尺寸的内停留。检查大小减少采取以下形式:
16384
8088
4259
2207
1110
540
246
94
32
3
导致在页面生成和1完成9刷新。
这仍然需要一些关于压缩率的猜测,以便知道什么会压缩到填充块大小以上。但它给了我一个非常好的提示,即使用部分解压缩。在我的场景中,我可以在“未分页”文件的“尾部”使用缓冲区,并在缓冲区超过页面大小时对其进行分页。我会写更多的测试,看看它是否适合这种情况。谢谢。 –
不需要猜测。对于第一遍,只是继续压缩,直到你过满了块。 –
在使用Comressor及其OutputStream的Java中时,输出大小在刷新之前不会更新。据我了解,冲洗导致压缩循环,所以为了防止调用冲洗太频繁,我需要估计。 –