我正在尝试编写一个compress 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字节长
怎么回事?
答案 0 :(得分:6)
在测试中,您使用一组随机字符初始化缓冲区。
GZIP由两部分组成:
前者很大程度上依赖于输入中的重复序列。基本上它说的是:“接下来的10个字符与盯着索引X的10个字符相同”。 在你的情况下,(可能)没有这样的重复序列,因此第一算法没有压缩。
另一方面,霍夫曼编码应该起作用,但总的来说,GZIP开销(例如,存储所使用的霍夫曼编码)超过了压缩输入的优点。如果您使用真实文件测试算法,您将获得一些有意义的结果。
在尝试压缩XML等结构化文件时,通常会获得最佳结果。
答案 1 :(得分:1)
这是因为压缩通常在中到大数据长度(1023字节非常小)上工作得很好,而且它对包含重复模式而不是随机数据的数据也起到最佳效果。