Java利用ZipOutputStream进行高效压缩的技巧详解

 更新时间:2025年07月07日 08:14:35   作者:心之语歌  
ZipOutputStream 是 Java 标准库中用于 创建 ZIP 文件 的核心类,位于 java.util.zip 包中,本文主要和大家介绍了Java如何使用ZipOutputStream进行高效压缩,有需要的可以了解下

简介

ZipOutputStream 是 Java 标准库中用于 创建 ZIP 文件 的核心类,位于 java.util.zip 包中。它允许你将多个文件或字节流写入一个 ZIP 压缩包,并支持设置压缩级别、编码方式等参数。

基本概念

ZipOutputStream的作用

  • 将多个文件(或字节数组)打包成一个 ZIP 文件。
  • 支持添加多个条目(ZipEntry),每个条目代表 ZIP 中的一个文件。
  • 可控制压缩级别、编码格式、注释等。

常用方法说明

方法描述
putNextEntry(ZipEntry entry)开始写入一个新的 ZIP 条目(文件)
closeEntry()关闭当前 ZIP 条目,准备写入下一个
write(byte[] b, int off, int len)写入当前条目的内容(字节数据)
setLevel(int level)设置压缩级别(0~9)
setComment(String comment)设置整个 ZIP 文件的注释
finish()完成写入,但不关闭底层输出流(可选)

可选的压缩级别(取值范围:0 ~ 9)

级别含义特点
Deflater.NO_COMPRESSION (0)不压缩速度最快,ZIP 文件最大
Deflater.BEST_SPEED (1)最快压缩压缩率低,速度快
Deflater.DEFAULT_COMPRESSION (6)默认压缩平衡压缩率与速度
Deflater.BEST_COMPRESSION (9)最佳压缩压缩率最高,速度最慢

本地保存

import java.io.*;
import java.nio.file.*;
import java.util.zip.*;

public class ZipDemo {
    public static void main(String[] args) throws IOException {
        // 源文件夹路径:要压缩的文件所在的目录
        String sourceDir = "path/to/folder";

        // 输出 ZIP 文件路径:生成的压缩包保存的位置和名称
        String zipFilePath = "output.zip";

        // 使用 try-with-resources 自动关闭资源(FileOutputStream 和 ZipOutputStream)
        try (FileOutputStream fos = new FileOutputStream(zipFilePath);
             ZipOutputStream zos = new ZipOutputStream(fos)) {

            // 设置 ZIP 压缩级别为最佳压缩(压缩率最高,但速度较慢)
            zos.setLevel(Deflater.BEST_COMPRESSION);

            // 遍历源目录下的所有文件(包括子目录中的文件)
            Files.walk(Paths.get(sourceDir))
                 // 过滤掉目录,只保留文件
                 .filter(path -> !Files.isDirectory(path))
                 // 对每个文件执行以下操作
                 .forEach(path -> {
                     try {
                         // 构建相对路径字符串:sourceDir + 文件分隔符 + 文件名
                         // 注意:这会导致 ZIP 中的路径包含 sourceDir 的前缀
                         String relativePath = sourceDir + File.separator + path.getFileName();

                         // 创建一个 ZIP 条目(即 ZIP 包中的一个文件)
                         ZipEntry zipEntry = new ZipEntry(relativePath);

                         // 开始写入该条目到 ZIP 流中
                         zos.putNextEntry(zipEntry);

                         // 读取文件内容为字节数组
                         byte[] bytes = Files.readAllBytes(path);

                         // 将文件内容写入 ZIP 输出流
                         zos.write(bytes, 0, bytes.length);

                         // 关闭当前 ZIP 条目,准备写入下一个文件
                         zos.closeEntry();

                     } catch (IOException e) {
                         // 如果写入失败,打印错误信息并输出异常堆栈
                         System.err.println("写入 ZIP 失败: " + path);
                         e.printStackTrace();
                     }
                 });
        }
        // try-with-resources 会自动关闭 fos 和 zos,无需手动 close()
    }
}

ZIP 文件网络流下载

response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachment; filename=\"streamed_files.zip\"");

try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream(), StandardCharsets.UTF_8)) {
    zipOut.setLevel(Deflater.BEST_SPEED);

    for (User u : userList) {
        String fileName = String.format("%sxxxx.docx", u.getNickName());

        try {
            zipOut.putNextEntry(new ZipEntry(fileName));
            byte[] docBytes = genDocx(u).toByteArray();
            zipOut.write(docBytes, 0, docBytes.length);
            zipOut.closeEntry();
        } catch (IOException e) {
            log.error("写入 ZIP 条目失败: {}", fileName, e);
            throw new IOException("生成 ZIP 条目时出错: " + fileName, e);
        }
    }

} catch (IOException ex) {
    log.error("导出 ZIP 异常", ex);
    throw new RuntimeException("导出异常");
}

1. 设置响应头

response.setContentType("application/zip");
  • 设置 HTTP 响应内容类型为 application/zip,告诉浏览器这是一个 ZIP 文件。
  • 浏览器收到后会识别为压缩文件,通常会触发下载行为。
response.setHeader("Content-Disposition", "attachment; filename=\"streamed_files.zip\"");
  • 设置响应头 Content-Disposition,值为 attachment 表示让浏览器不要在页面中显示该内容,而是提示用户下载。
  • filename="streamed_files.zip" 指定下载时的默认文件名。

2. 创建 ZIP 输出流(使用 try-with-resources)

try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream(), StandardCharsets.UTF_8)) {
  • 使用 try-with-resources 自动关闭资源,确保最后流会被正确关闭。
  • 创建了一个 ZipOutputStream,它是一个用于写入 ZIP 文件格式的输出流。
  • 第二个参数 StandardCharsets.UTF_8 是为了支持中文文件名编码(避免解压时出现乱码)。

注意:部分旧系统或工具(如 Windows 自带解压器)可能不识别 UTF-8 编码的 ZIP 文件名,建议使用 7-Zip、WinRAR 或 Mac 解压工具。

3. 设置压缩级别(可选)

zipOut.setLevel(Deflater.BEST_SPEED);
  • 设置压缩级别为最快压缩模式。
  • 这样可以减少服务器 CPU 占用,适合对压缩率要求不高但希望快速响应用户的场景。
  • 可替换为:
    • Deflater.DEFAULT_COMPRESSION(默认)
    • Deflater.BEST_COMPRESSION(最佳压缩)

4. 生成文件加入到 zip 流

zipOut.putNextEntry(new ZipEntry(fileName));
  • 在 ZIP 包中创建一个新的条目(即文件),名字是上面生成的文件名。
  • 每次调用 putNextEntry() 后必须调用 closeEntry() 才能继续添加下一个文件。
byte[] docBytes = genDocx(u).toByteArray();
zipOut.write(docBytes, 0, docBytes.length);
  • 调用 genDocx(u) 方法生成当前用户的 .docx 文件内容(返回的是 ByteArrayOutputStream)。
  • 将其转为字节数组后写入 ZIP 流中。
zipOut.closeEntry();

关闭当前 ZIP 条目,准备写入下一个文件。

到此这篇关于Java利用ZipOutputStream进行高效压缩的技巧详解的文章就介绍到这了,更多相关Java ZipOutputStream压缩内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java 分割csv数据的实例详解

    java 分割csv数据的实例详解

    这篇文章主要介绍了java 分割csv数据的实例详解的相关资料,这里提供了简单实例,需要的朋友可以参考下
    2017-07-07
  • Java实现SHA算法的方法详解

    Java实现SHA算法的方法详解

    这篇文章主要介绍了Java实现SHA算法的方法,结合实例形式较为详细的分析了Java实现sha算法的原理、实现与使用相关操作技巧,需要的朋友可以参考下
    2018-03-03
  • Java8中Stream的详细使用方法大全

    Java8中Stream的详细使用方法大全

    Java8的另一大亮点Stream,它与java.io包里的InputStream和OutputStream是完全不同的概念,下面这篇文章主要给大家介绍了关于Java8中Stream详细使用方法的相关资料,需要的朋友可以参考下
    2022-06-06
  • mybatis-plus分页查询total=0问题及解决方案

    mybatis-plus分页查询total=0问题及解决方案

    这篇文章主要介绍了mybatis-plus分页查询total=0问题及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2026-03-03
  • Java实现学生信息管理系统超详细教程

    Java实现学生信息管理系统超详细教程

    这篇文章主要介绍了一个简单的Java学生信息管理系统,使用ArrayList集合存储学生对象信息,并实现了添加、删除、修改和查看学生信息的功能,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2025-01-01
  • 递归出现栈溢出stackoverflow的问题及解决

    递归出现栈溢出stackoverflow的问题及解决

    这篇文章主要介绍了关于递归出现栈溢出stackoverflow的问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-09-09
  • Java异步非阻塞编程的几种方式总结

    Java异步非阻塞编程的几种方式总结

    这篇文章主要介绍了Java异步非阻塞编程的几种方式总结,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06
  • 把Java程序打包成jar文件包并执行的方法

    把Java程序打包成jar文件包并执行的方法

    这篇文章主要介绍了把Java程序打包成jar文件包并执行的方法,非常具有实用价值,需要的朋友可以参考下
    2017-10-10
  • Java接口测试之日志框架Logback的具体使用

    Java接口测试之日志框架Logback的具体使用

    本文主要介绍了Java接口测试之日志框架Logback的具体使用,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • 解决MyEclipse出现the user operation is waiting的问题

    解决MyEclipse出现the user operation is waiting的问题

    今天做项目的时候每次修改代码保存后都会跳出一个框框,然后就有两个进度条,上面写the user operation is wating...小编去网上查了查解决了这个问题,下面跟大家分享一下。
    2018-04-04

最新评论