Java中Deflater基于zlib的DEFLATE算法实现无损压缩,支持内存压缩、可设压缩级别,需手动管理输入输出状态;设no-wrap=true可输出纯DEFLATE流,适用于WebSocket等协议。

Java 中借助 Deflater 进行数据压缩,核心是使用 zlib 标准的 DEFLATE 算法(无损压缩),它被广泛用于 ZIP、GZIP、PNG 等格式。Java 的 java.util.zip.Deflater 类提供了对底层 zlib 的封装,支持内存中压缩字节数组,无需文件 I/O。
理解 Deflater 的基本用法
Deflater 是一个可重用的状态机,需手动管理压缩流程:设置输入、调用 deflate() 输出压缩数据、判断是否完成。它不自动处理流边界,适合控制粒度强的场景(如协议包压缩、自定义消息体压缩)。
- 创建实例时可指定压缩级别(
Deflater.BEST_COMPRESSION到Deflater.NO_COMPRESSION),默认为Deflater.DEFAULT_COMPRESSION - 必须调用
setInput(byte[])提供原始数据,再反复调用deflate(byte[])获取压缩结果 - 当
deflate()返回值为 0 且needsInput()为 true 时,表示输入已处理完;若还需输出,需继续调用直到finished()返回 true
典型压缩代码示例(无头格式)
以下是一个简洁可靠的内存压缩方法,返回纯 DEFLATE 压缩字节(不含 zlib 或 gzip 头/尾):
public static byte[] deflate(byte[] data) {
Deflater deflater = new Deflater(Deflater.BEST_COMPRESSION, true); // true 表示 no-wrap,即纯 DEFLATE
deflater.setInput(data);
deflater.finish();
ByteArrayOutputStream out = new ByteArrayOutputStream(data.length);
byte[] buffer = new byte[1024];
while (!deflater.finished()) {
int count = deflater.deflate(buffer);
out.write(buffer, 0, count);
}
deflater.end();
return out.toByteArray();
}
注意:new Deflater(level, true) 中的 true 参数禁用 zlib 封装头(RFC 1950),仅输出 RFC 1951 定义的原始 DEFLATE 流——这对某些通信协议(如 WebSocket permessage-deflate 扩展)是必需的。
立即学习“Java免费学习笔记(深入)”;
与 GZIPOutputStream 的关键区别
别混淆 Deflater 和高级流封装类:
-
GZIPOutputStream自动添加 gzip 格式头(10 字节)、CRC32 校验和尾部长度,适合文件或 HTTP 响应体 -
Deflater(尤其no-wrap=true)只输出压缩后字节,更轻量,适合嵌入二进制协议或需要精确控制格式的场景 - 若需标准 gzip 格式,直接用
GZIPOutputStream更安全;若需 zlib 兼容(含头尾),用Deflater默认构造(no-wrap=false)
常见坑与注意事项
实际使用中容易忽略几个细节:
- 每次压缩前必须调用
setInput(),重复压缩不同数据时要确保前一次已finish()或end() -
deflate()可能返回 0,不代表错误,需结合needsInput()和finished()判断状态 - 缓冲区大小影响性能但不影响正确性,1KB~8KB 是常用范围;太小会频繁拷贝,太大浪费内存
- 压缩空数组或 null 需提前判空,
Deflater不做空值保护
基本上就这些。掌握状态流转和 no-wrap 含义,就能稳稳用好 Deflater。









