将数据放入固定长度的缓冲区

时间:2017-07-28 09:42:59

标签: java deflate

对于一个项目,我使用大量加密数据工作很多,这些数据用得很重。由于解密比充气要长得多,我愿意在加密和存储之前对数据进行收缩。

我面临的困难是数据存储在固定长度的块或页面中。磁盘上的这些块需要保持固定长度,以便快速查找页面。所以基本上我试图将尽可能多的数据放入固定大小的页面。

目前我正试图找到一个好方法。但是,此时每次添加数据并且未压缩的大小接近页面限制时,我都会陷入压缩大小。 (因为如果数据的熵非常高,理论上数据在理论上也会因压缩而增长一点)。目前,我正在尝试以下方法:

    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;
            }
        }

该解决方案的压缩比与原始压缩比(在一个块中)相差不大,并且保持在所需输出大小的8个字节内。支票尺寸减小采用以下形式:

 16384
 8088
 4259
 2207
 1110
 540
 246
 94
 32
 3

在页面生成和完成1次期间导致9次刷新。

1 个答案:

答案 0 :(得分:1)

放气并不适合这种情况,但是如果让它尝试几次,可以强迫它非常接近填充块。通过三次压缩传递来查看fitblk,它完全符合您的要求,包括它们之间的两次解压缩。

想法是压缩超过块大小,仅解压缩块大小,然后仅重新压缩解压缩的内容。你这样做了两次,以便非常接近,或者很多时候,完全填满了这块。