Java对象压缩序列化需按ObjectOutputStream→DeflaterOutputStream→FileOutputStream顺序构建流链,确保序列化后立即压缩;反序列化须用InflaterInputStream配合ObjectInputStream还原;需显式flush并按逆序关闭流,且可调Deflater压缩级别优化效率。

Java 中可以通过将 ObjectOutputStream 包装在 DeflaterOutputStream 外层,实现对象的压缩序列化。关键在于正确构建流链:先用 DeflaterOutputStream 压缩字节,再由 ObjectOutputStream 负责序列化逻辑 —— 注意顺序不能颠倒,否则会因缓冲或关闭行为导致异常。
流包装顺序必须是 ObjectOutputStream → DeflaterOutputStream → FileOutputStream
实际写入时,数据流向是:对象 → ObjectOutputStream(序列化成字节)→ DeflaterOutputStream(压缩字节)→ 文件/输出目标。因此构造顺序要“从外向内”嵌套:
- 最里层是
FileOutputStream(或其他OutputStream) - 中间套一层
DeflaterOutputStream,启用压缩 - 最外层才是
ObjectOutputStream,确保它写入的是已压缩的目标流
错误做法(如把 ObjectOutputStream 放里面)会导致 writeObject 写到未压缩流,后续压缩无效,甚至因 ObjectOutputStream 构造时写魔数失败而抛出 IOException。
需要手动刷新和关闭,避免压缩数据丢失
DeflaterOutputStream 内部使用 Deflater 缓冲压缩数据,ObjectOutputStream 也有自己的缓冲区。若不显式刷新,部分压缩块可能滞留在缓冲区中未写出。
立即学习“Java免费学习笔记(深入)”;
- 调用
objectOut.flush()确保所有序列化数据进入DeflaterOutputStream - 再调用
deflaterOut.flush()强制压缩器输出剩余压缩数据 - 最后关闭流(按相反顺序:
objectOut.close()→deflaterOut.close()→fileOut.close()),其中close()会隐式触发flush(),但显式调用更可控
反序列化时必须用 InflaterInputStream 配合 ObjectInputStream
压缩序列化的文件不能直接用普通 ObjectInputStream 读取。必须还原相同的流链:
- 用
FileInputStream打开文件 - 包装为
InflaterInputStream(对应压缩端的DeflaterOutputStream) - 再包装为
ObjectInputStream
注意:InflaterInputStream 解压时若遇到损坏或非压缩数据,会抛出 DataFormatException;若流末尾有未解压完的数据,也可能报 EOFException,需检查压缩/解压两端是否严格匹配。
可选:调整 Deflater 压缩级别提升效率
DeflaterOutputStream 构造时可传入 Deflater 实例,自定义压缩策略:
-
new Deflater(Deflater.BEST_COMPRESSION):压缩率最高,速度慢 -
new Deflater(Deflater.DEFLATED, true):启用 nowrap 模式(不加 zlib 头/尾),适合与InflaterInputStream配合(默认也用 nowrap) - 默认构造使用
Deflater.DEFAULT_COMPRESSION,平衡速度与体积
若压缩后体积未明显减小,可能是对象本身序列化后冗余少(如大量基本类型),或字符串内容已较紧凑,此时压缩收益有限。


















