为什么gzip压缩缓冲区大小为大于未压缩的缓冲?(Why gzip compressed buffe

2019-11-02 05:00发布

我试图写一个压缩utils的类。
但在测试过程中,我发现结果比原来的缓冲区更大。
是我的代码吗?

请参阅代码:

/**
 * This class provide compress ability
 * <p>
 * Support:
 * <li>GZIP
 * <li>Deflate
 */
public class CompressUtils {
    final public static int DEFAULT_BUFFER_SIZE = 4096; // Compress/Decompress buffer is 4K

    /**
     * GZIP Compress
     * 
     * @param data The data will be compressed
     * @return The compressed data
     * @throws IOException
     */
    public static byte[] gzipCompress(byte[] data) throws IOException {
        Validate.isTrue(ArrayUtils.isNotEmpty(data));

        ByteArrayInputStream bis = new ByteArrayInputStream(data);
        ByteArrayOutputStream bos = new ByteArrayOutputStream();

        try {
            gzipCompress(bis, bos);
            bos.flush();
            return bos.toByteArray();
        } finally {
            bis.close();
            bos.close();
        }
    }

    /**
     * GZIP Decompress
     * 
     * @param data The data to be decompressed
     * @return The decompressed data
     * @throws IOException
     */
    public static byte[] gzipDecompress(byte[] data) throws IOException {
        Validate.isTrue(ArrayUtils.isNotEmpty(data));

        ByteArrayInputStream bis = new ByteArrayInputStream(data);
        ByteArrayOutputStream bos = new ByteArrayOutputStream();

        try {
            gzipDecompress(bis, bos);
            bos.flush();
            return bos.toByteArray();
        } finally {
            bis.close();
            bos.close();
        }
    }

    /**
     * GZIP Compress
     * 
     * @param is The input stream to be compressed
     * @param os The compressed result
     * @throws IOException
     */
    public static void gzipCompress(InputStream is, OutputStream os) throws IOException {
        GZIPOutputStream gos = null;

        byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
        int count = 0;

        try {
            gos = new GZIPOutputStream(os);
            while ((count = is.read(buffer)) != -1) {
                gos.write(buffer, 0, count);
            }
            gos.finish();
            gos.flush();
        } finally {
            if (gos != null) {
                gos.close();
            }
        }
    }

    /**
     * GZIP Decompress
     * 
     * @param is The input stream to be decompressed
     * @param os The decompressed result
     * @throws IOException
     */
    public static void gzipDecompress(InputStream is, OutputStream os) throws IOException {
        GZIPInputStream gis = null;

        int count = 0;
        byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];

        try {
            gis = new GZIPInputStream(is);
            while ((count = is.read(buffer)) != -1) {
                os.write(buffer, 0, count);
            }
        } finally {
            if (gis != null) {
                gis.close();
            }
        }
    }
}

而这里的测试代码:

public class CompressUtilsTest {
    private Random random = new Random();

    @Test
    public void gzipTest() throws IOException {
        byte[] buffer = new byte[1023];
        random.nextBytes(buffer);
        System.out.println("Orignal: " + Hex.encodeHexString(buffer));

        byte[] result = CompressUtils.gzipCompress(buffer);
        System.out.println("Compressed: " + Hex.encodeHexString(result));

        byte[] decompressed = CompressUtils.gzipDecompress(result);
        System.out.println("DeCompressed: " + Hex.encodeHexString(decompressed));

        Assert.assertArrayEquals(buffer, decompressed);
    }
}

其结果是:原来是长压缩1023个字节是1036个字节长

它是如何发生的?

Answer 1:

在您的测试初始化​​一组随机字符缓冲区。

GZIP由两个部分组成:

  1. LZW压缩
  2. 使用霍夫曼码的编码

前者在很大程度上依赖于输入重复序列。 基本上,它说是这样的:“接下来的10个字符是一样的10个字符在指数X盯着”。 在您的情况下,存在(可能)没有这样的重复序列,从而没有压缩由所述第一算法。

在另一方面,霍夫曼编码应该工作,但在总的GZIP开销(存储所述使用霍夫曼编码,例如)远远超过压缩所述输入的优点。

如果你与真正的文件来测试你的算法,你会得到一些有意义的结果。

试图压缩结构的文件,如XML时,最好的结果通常收购。



Answer 2:

这是因为压缩通常适用于大中型数据长度大(1023个字节是相当小),而且它也可以最好对包含重复的图案不是随机的人的数据。



文章来源: Why gzip compressed buffer size is greater then uncompressed buffer?
标签: java gzip