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压缩内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringMVC工作原理实例详解

    SpringMVC工作原理实例详解

    这篇文章主要介绍了SpringMVC工作原理实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03
  • Java中sort排序函数实例详解

    Java中sort排序函数实例详解

    我们经常使用java中的sort排序,确实好用,但是其中原理大多数人都是不了解的,下面这篇文章主要给大家介绍了关于Java中sort排序函数的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-06-06
  • Java ==,equals()与hashcode()的使用

    Java ==,equals()与hashcode()的使用

    本文主要介绍了Java ==,equals()与hashcode()的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-05-05
  • spring boot 配置freemarker及如何使用freemarker渲染页面

    spring boot 配置freemarker及如何使用freemarker渲染页面

    springboot中自带的页面渲染工具为thymeleaf 还有freemarker这两种模板引擎,本文重点给大家介绍spring boot 配置freemarker及如何使用freemarker渲染页面,感兴趣的朋友一起看看吧
    2023-10-10
  • Java类之间的关系图_动力节点Java学院整理

    Java类之间的关系图_动力节点Java学院整理

    在Java以及其他的面向对象设计模式中,类与类之间主要有6种关系,他们分别是:依赖、关联、聚合、组合、继承、实现。他们的耦合度依次增强,有兴趣的可以了解一下
    2017-08-08
  • 解决Springboot项目报错:java:错误:不支持发行版本 17

    解决Springboot项目报错:java:错误:不支持发行版本 17

    这篇文章主要给大家介绍了关于解决Springboot项目报错:java:错误:不支持发行版本17的相关资料,这个错误意味着你的Spring Boot项目正在使用Java 17这个版本,但是你的项目中未配置正确的Java版本,需要的朋友可以参考下
    2023-08-08
  • 6种常见的SpringBoot拦截器使用场景及实现方式

    6种常见的SpringBoot拦截器使用场景及实现方式

    这篇文章主要为大家详细介绍了SpringBoot中6种常见的拦截器使用场景及其实现方式,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2025-04-04
  • Mybatis批量新增的三种实现方式

    Mybatis批量新增的三种实现方式

    文章讲述了在Java中进行批量操作的最佳实践,包括使用MyBatis的ExecutorType.BATCH模式,作者建议根据实际需求选择是否进行批量操作,因为批量操作并不总是能提升性能,且有副作用,如无法获取自增ID等
    2024-12-12
  • springMVC详细介绍

    springMVC详细介绍

    下面小编就为大家带来一篇基于Spring MVC 详细介绍。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2021-07-07
  • 浅谈对象与Map相互转化

    浅谈对象与Map相互转化

    这篇文章主要介绍了利用BeanMap进行对象与Map的相互转换,在文中列举了完整代码,需要的朋友可以参考下。
    2017-09-09

最新评论