【发布时间】:2012-03-03 02:52:12
【问题描述】:
我想压缩/解压缩和序列化/反序列化字符串内容。我正在使用以下两个静态函数。
/**
* Compress data based on the {@link Deflater}.
*
* @param pToCompress
* input byte-array
* @return compressed byte-array
* @throws NullPointerException
* if {@code pToCompress} is {@code null}
*/
public static byte[] compress(@Nonnull final byte[] pToCompress) {
checkNotNull(pToCompress);
// Compressed result.
byte[] compressed = new byte[] {};
// Create the compressor.
final Deflater compressor = new Deflater();
compressor.setLevel(Deflater.BEST_SPEED);
// Give the compressor the data to compress.
compressor.setInput(pToCompress);
compressor.finish();
/*
* Create an expandable byte array to hold the compressed data.
* You cannot use an array that's the same size as the orginal because
* there is no guarantee that the compressed data will be smaller than
* the uncompressed data.
*/
try (ByteArrayOutputStream bos = new ByteArrayOutputStream(pToCompress.length)) {
// Compress the data.
final byte[] buf = new byte[1024];
while (!compressor.finished()) {
final int count = compressor.deflate(buf);
bos.write(buf, 0, count);
}
// Get the compressed data.
compressed = bos.toByteArray();
} catch (final IOException e) {
LOGWRAPPER.error(e.getMessage(), e);
throw new RuntimeException(e);
}
return compressed;
}
/**
* Decompress data based on the {@link Inflater}.
*
* @param pCompressed
* input string
* @return compressed byte-array
* @throws NullPointerException
* if {@code pCompressed} is {@code null}
*/
public static byte[] decompress(@Nonnull final byte[] pCompressed) {
checkNotNull(pCompressed);
// Create the decompressor and give it the data to compress.
final Inflater decompressor = new Inflater();
decompressor.setInput(pCompressed);
byte[] decompressed = new byte[] {};
// Create an expandable byte array to hold the decompressed data.
try (final ByteArrayOutputStream bos = new ByteArrayOutputStream(pCompressed.length)) {
// Decompress the data.
final byte[] buf = new byte[1024];
while (!decompressor.finished()) {
try {
final int count = decompressor.inflate(buf);
bos.write(buf, 0, count);
} catch (final DataFormatException e) {
LOGWRAPPER.error(e.getMessage(), e);
throw new RuntimeException(e);
}
}
// Get the decompressed data.
decompressed = bos.toByteArray();
} catch (final IOException e) {
LOGWRAPPER.error(e.getMessage(), e);
}
return decompressed;
}
然而,与未压缩的值相比,即使我正在缓存解压缩的结果,它的速度也要慢几个数量级,并且只有在确实需要内容时才对这些值进行解压缩。
也就是说,它用于类似 DOM 的可持久树结构和强制解压缩字符串值的 XPath 查询大约是 50 倍,甚至更慢(不是真正的基准测试,只是执行的单元测试)。我的笔记本电脑甚至在一些单元测试后冻结(每次,检查大约 5 次),因为 Eclipse 由于磁盘 I/O 太重而不再响应等等。我什至将压缩级别设置为Deflater.BEST_SPEED,而其他压缩级别可能会更好,也许我提供了一个可以为resources 设置的配置选项参数。也许我搞砸了,因为我以前没有使用过放气机。我什至只压缩字符串长度大于 10 的内容。
编辑:在考虑将 Deflater 实例提取到静态字段之后,似乎创建一个 deflater 和 inflater 的实例非常成本很高,因为性能瓶颈已经消失,也许没有微基准或类似的东西我可以'看不到任何性能损失 :-) 我只是在使用新输入之前重置放气器/充气器。
【问题讨论】:
-
您如何衡量压缩和解压缩算法的性能?您能否分享您对此的想法/代码?您是否在计算算法的压缩率和压缩时间?如果是这样,你能和我分享一下经验吗?我已经为随机字符串实现了压缩和解压缩算法,现在我需要通过计算压缩率、压缩时间等来衡量我的算法的性能。任何形式的帮助都将不胜感激。谢谢!
标签: java compression