407. Java 文件操作基础 - 压缩二进制流(GZIP)

14 阅读2分钟

407. Java 文件操作基础 - 压缩二进制流(GZIP)

1️⃣ 概述

在 Java 中,装饰器模式(Decorator Pattern 被广泛用于 I/O 流的增强功能,比如处理 GZIP 文件。

  • GZIPdeflate 算法 的一种实现,规范参考 RFC 1952
  • Java 提供两个类来支持 GZIP 压缩和解压:
    • GZIPOutputStream → 写入压缩数据
    • GZIPInputStream → 读取压缩数据

这些类都是 字节流的装饰器

  • 它们继承自 OutputStreamInputStream
  • 不增加新方法,只是覆盖了字节的读写逻辑
  • 可以和 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);
    }
}

🔑 讲解

  1. 流的装饰顺序
Files.newOutputStream() → GZIPOutputStream → OutputStreamWriter
  1. 效果
    • 原始文本文件可能是 600+ 字节
    • 压缩后,文件大小明显减小,例如:size = 377
  2. 兼容性
    • 生成的 .gz 文件可用任意 GZIP 软件解压
  3. 好处
    • 原有写入逻辑几乎不变
    • 只需在 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);
    }
}

🔑 讲解

  1. 流的装饰顺序
Files.newInputStream() → GZIPInputStream → InputStreamReader → BufferedReader → Stream<String>
  1. 重点
    • GZIPInputStream 装饰普通输入流,实现解压
    • 后续逻辑与普通文本文件读取完全一致
    • 利用 BufferedReader.lines() + Stream API 处理文本
  2. 好处
    • 读取压缩文件与普通文本文件几乎无差别
    • 保留字符流处理、按行读取、Stream 操作的能力

4️⃣ 小结

  • 装饰器模式在 I/O 中非常强大:
    • 可以在不改变原始逻辑的前提下增加功能
    • 例如支持压缩、缓冲、按行处理等
  • GZIP 流组合
    • 写入:OutputStream → GZIPOutputStream → OutputStreamWriter
    • 读取:InputStream → GZIPInputStream → InputStreamReader → BufferedReader
  • 实践要点
    • try-with-resources 确保所有流关闭
    • GZIP 流只影响字节的写入/读取,不影响字符处理逻辑