407. Java 文件操作基础 - 压缩二进制流(GZIP)
1️⃣ 概述
在 Java 中,装饰器模式(Decorator Pattern) 被广泛用于 I/O 流的增强功能,比如处理 GZIP 文件。
GZIP是deflate算法 的一种实现,规范参考RFC 1952- Java 提供两个类来支持 GZIP 压缩和解压:
GZIPOutputStream→ 写入压缩数据GZIPInputStream→ 读取压缩数据
这些类都是 字节流的装饰器:
- 它们继承自
OutputStream或InputStream - 不增加新方法,只是覆盖了字节的读写逻辑
- 可以和
OutputStreamWriter/InputStreamReader配合,实现字符与压缩流的组合
💡 重点:使用装饰器模式,你只需在原有的写入/读取代码上小幅修改就能支持压缩文件。
2️⃣ Writing Data with GZIPOutputStream
示例代码:将文本写入 GZIP 文件。
import java.nio.file.*;
import java.io.*;
import java.util.zip.GZIPOutputStream;
public class GzipWriteExample {
public static void main(String[] args) throws IOException {
String message = "From fairest creatures we desire increase,\n"
+ "That thereby beauty's rose might never die,..."; // 示例文本
Path path = Path.of("files/sonnet.txt.gz");
try (var outputStream = Files.newOutputStream(path);
var gzipOutputStream = new GZIPOutputStream(outputStream);
var writer = new OutputStreamWriter(gzipOutputStream)) {
writer.write(message);
} catch (IOException e) {
e.printStackTrace();
}
long size = Files.size(path);
System.out.println("size = " + size);
}
}
🔑 讲解
- 流的装饰顺序:
Files.newOutputStream() → GZIPOutputStream → OutputStreamWriter
- 效果:
- 原始文本文件可能是 600+ 字节
- 压缩后,文件大小明显减小,例如:
size = 377
- 兼容性:
- 生成的
.gz文件可用任意 GZIP 软件解压
- 生成的
- 好处:
- 原有写入逻辑几乎不变
- 只需在 OutputStream 上加一层 GZIP 装饰器
3️⃣ Reading Data with GZIPInputStream
示例代码:读取 GZIP 压缩文件。
import java.nio.file.*;
import java.io.*;
import java.util.stream.*;
import java.util.zip.GZIPInputStream;
import java.util.stream.Collectors;
public class GzipReadExample {
public static void main(String[] args) throws IOException {
Path path = Path.of("files/sonnet.txt.gz");
String sonnet = null;
try (var inputStream = Files.newInputStream(path);
var gzipInputStream = new GZIPInputStream(inputStream);
var reader = new InputStreamReader(gzipInputStream);
var bufferedReader = new BufferedReader(reader);
var lines = bufferedReader.lines()) {
// 将所有行收集为完整文本
sonnet = lines.collect(Collectors.joining("\n"));
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("sonnet = \n" + sonnet);
}
}
🔑 讲解
- 流的装饰顺序:
Files.newInputStream() → GZIPInputStream → InputStreamReader → BufferedReader → Stream<String>
- 重点:
GZIPInputStream装饰普通输入流,实现解压- 后续逻辑与普通文本文件读取完全一致
- 利用
BufferedReader.lines()+ Stream API 处理文本
- 好处:
- 读取压缩文件与普通文本文件几乎无差别
- 保留字符流处理、按行读取、Stream 操作的能力
4️⃣ 小结
- 装饰器模式在 I/O 中非常强大:
- 可以在不改变原始逻辑的前提下增加功能
- 例如支持压缩、缓冲、按行处理等
- GZIP 流组合:
- 写入:
OutputStream → GZIPOutputStream → OutputStreamWriter - 读取:
InputStream → GZIPInputStream → InputStreamReader → BufferedReader
- 写入:
- 实践要点:
- try-with-resources 确保所有流关闭
- GZIP 流只影响字节的写入/读取,不影响字符处理逻辑