<aside> <img src="notion://custom_emoji/c233e7bc-acd0-812b-a811-00030dcd1edc/29e3e7bc-acd0-808e-ac64-007a3fac687d" alt="notion://custom_emoji/c233e7bc-acd0-812b-a811-00030dcd1edc/29e3e7bc-acd0-808e-ac64-007a3fac687d" width="40px" />
在 Java 中,压缩流是一种特殊的I/O流(装饰器流),它允许你在读取或写入数据的同时,自动对数据进行压缩或解压缩。这对于节省存储空间或减少网络传输数据量非常有用。
</aside>
这些功能主要由 java.util.zip 包提供。我们主要关注两种最常见的压缩格式:GZIP 和 ZIP。
你需要理解,Java 的压缩流是装饰器(Decorator)。它们不能独立工作,必须“包装”在另一个基础流(如 FileInputStream 或 FileOutputStream)之上。
程序 -> GZIPOutputStream -> FileOutputStream -> 文件 (compressed.gz)程序 <- GZIPInputStream <- FileInputStream <- 文件 (compressed.gz)GZIP (GNU zip) 是一种常见的压缩格式,通常用于压缩单个文件或单个数据流。在 Unix/Linux 系统中,你经常会看到 .gz 后缀的文件。
GZIPOutputStream:压缩数据它用于将数据压缩为 GZIP 格式,并写入到底层输出流。
关键点:
GZIPOutputStream 写入数据时,它会先压缩这些数据,然后再把压缩后的数据写入它所包装的流(例如 FileOutputStream)。GZIPOutputStream(最好使用 try-with-resources)。关闭流会触发 finish() 方法,这个方法会写入所有剩余的压缩数据和 GZIP 尾部信息。如果不关闭,你得到的文件将是不完整的或已损坏的。示例:压缩一个文件
import java.io.*;
import java.util.zip.GZIPOutputStream;
public class GzipCompress {
public static void main(String[] args) {
String sourceFile = "source.txt";
String compressedFile = "source.txt.gz";
// 使用 try-with-resources 自动关闭流
try (
// 1. 创建一个文件输入流来读取源文件
FileInputStream fis = new FileInputStream(sourceFile);
// 2. 创建一个文件输出流来写入压缩文件
FileOutputStream fos = new FileOutputStream(compressedFile);
// 3. 创建 GZIP 输出流来包装文件输出流
GZIPOutputStream gzipOS = new GZIPOutputStream(fos)
) {
byte[] buffer = new byte[8192]; // 缓冲区
int bytesRead;
// 4. 从源文件读取数据,并写入 GZIP 流
while ((bytesRead = fis.read(buffer)) != -1) {
gzipOS.write(buffer, 0, bytesRead);
}
System.out.println("文件压缩成功!");
} catch (IOException e) {
e.printStackTrace();
}
// GZIPOutputStream 和 FileOutputStream 在 try 块结束时会自动关闭
}
}
GZIPInputStream:解压数据它用于从一个底层输入流中读取 GZIP 格式的压缩数据,并在读取时自动解压。