讲师中心 微信公众号
AI工具推荐 视频效率加速

Java中的ZipInputStream与ZipOutputStream_实现文件压缩与解压的类库技巧

风丽吖_1211

风丽吖_1211

发布时间:2026-02-25 12:05:02

|

550人浏览过

|

来源于php中文网

原创

ZipInputStream抛ZipException: invalid CEN header根本原因是流被提前消费或复用;ZipOutputStream中文乱码因Windows默认GBK解析UTF-8文件名;解压大文件OOM因未流式处理;closeEntry()不可省略,否则ZIP结构损坏。

java中的zipinputstream与zipoutputstream_实现文件压缩与解压的类库技巧

ZipInputStream读取压缩包时为什么总抛ZipException: invalid CEN header

根本原因是流被提前消费或复用,比如把同一个InputStream传给多个ZipInputStream,或者在构造ZipInputStream前已调用过read()。ZIP格式依赖精确的字节偏移定位中央目录(CEN),任何前置读取都会破坏这个结构。

实操建议:

立即学习“Java免费学习笔记(深入)”;

Java调试
Java调试

通过 JDWP 实现 Java 远程调试:连接远程 JVM、设置断点、单步执行代码、查看变量值、获取调用栈。适用于需要调试远程 Java 应用、排查运行时状态、追踪代码执行流程的场景。 术语注解 JDWP:Java Debug Wire Protocol,Java 调试有线协议(Java 远程调试底层通信协议) remote JVM:远程 Java 虚拟机 step through code:代码单步调试(步入 / 步过 / 步出调试) inspect variables:变量查看 / 变量检视 stac

下载
  • 确保传入ZipInputStream的InputStream是**原始、未读取过的**;文件场景下优先用new FileInputStream(path),别用Files.newInputStream(Paths.get(...))后又手动read()
  • 不要对同一个流反复新建ZipInputStream——它不是线程安全的,也不支持重置
  • 若需多次遍历,先用Files.readAllBytes()加载到byte[],再用new ByteArrayInputStream(bytes)构造新流
  • 注意ZipInputStream.getNextEntry()返回null表示结束,但此时流位置已在末尾,不能再回头读

ZipOutputStream写入中文路径文件时乱码怎么办

JDK原生ZipOutputStream默认使用UTF-8编码写入文件名,但Windows系统自带解压工具(如资源管理器)默认按GBK解析,导致中文名显示为乱码。这不是bug,是标准兼容性问题。

实操建议:

立即学习“Java免费学习笔记(深入)”;

  • 明确目标解压环境:如果只在Linux/macOS或Java程序里解压,保持默认UTF-8即可
  • 若必须兼容Windows资源管理器,改用org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream,并调用setUseUnicodeExtraFields(ZipArchiveOutputStream.UnicodeExtraFieldPolicy.NOT_REQUIRED) + setEncoding("GBK")
  • 避免在文件名中混用中英文+特殊符号,某些旧版解压工具对Unicode extra field支持不全
  • 别试图用System.setProperty("sun.jnu.encoding", "GBK")——它不影响ZIP编码逻辑

用ZipInputStream逐个解压大文件时内存暴涨甚至OOM

ZipInputStream本身不缓存整个压缩包,但常见错误是把ZipEntry内容一次性读进byte[],比如用readAllBytes()或自己循环read()到大数组。一个100MB的entry会直接申请同等大小堆内存。

实操建议:

立即学习“Java免费学习笔记(深入)”;

  • 始终用缓冲区流式处理:try (InputStream is = zis; OutputStream os = Files.newOutputStream(dest)) { copy(is, os); }
  • 缓冲区大小选8192或65536(64KB),太小增加IO次数,太大无意义——JVM堆分配开销远高于缓冲区本身
  • 注意ZipEntry.getSize()可能返回-1(未知大小),别拿它来预分配数组
  • 解压到磁盘时,确保目标目录有足够空间,Files.createDirectories()要放在getOutputStream()之前,否则可能因路径不存在而失败

ZipOutputStream.closeEntry()和close()的调用顺序不能错

漏掉closeEntry()会导致当前条目数据损坏,后续条目写入失败;在closeEntry()前就close()则整个ZIP结构不完整,多数解压工具报“CRC校验失败”或“找不到中央目录”。

实操建议:

立即学习“Java免费学习笔记(深入)”;

  • 每个putNextEntry()后,必须配对closeEntry(),哪怕entry为空(比如只建目录)
  • 写完所有entry后再调用close()——这是写入中央目录(CEN)的时机
  • 用try-with-resources只能自动close(),无法保证closeEntry(),所以必须显式调用
  • 典型正确模式:
    zos.putNextEntry(new ZipEntry("a.txt"));  
    zos.write(data);  
    zos.closeEntry();  // 必须!  
    zos.putNextEntry(new ZipEntry("b/"));  
    zos.closeEntry();  // 目录也要closeEntry  
    zos.close();
实际项目里最常出问题的,是把ZipInputStream当普通流随意标记、重置或重复构造,以及忽略closeEntry()的强制语义——这两点没有绕过去的技巧,只能严格按ZIP规范走。

热门AI工具

更多
SkildArt
SkildArt Hot

SkildArt是一款AI文本写作工具,一站式 AI 视觉创作平台。

花生AI
花生AI Hot

一款AI视频创作工具,主要用于B站推出的AI视频创作工具,适合需要提升相关任务效率的用户。

UP简历
UP简历 Hot

一款AI办公效率工具,主要用于基于AI技术的免费在线简历制作工具,适合需要提升相关任务效率的用户。

音述AI
音述AI Hot

一款AI音频处理工具,主要用于音述AI是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区,适合需要提升相关任务效率的用户。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

超级简历WonderCV

一款AI办公效率工具,主要用于免费求职简历模版下载制作,应届生职场人必备简历制作神器,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

咔片AIPPT

一款在线AI演示文稿制作工具,可根据主题和内容需求辅助生成PPT结构与页面,提高演示材料制作效率。

相关专题

更多
c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

549

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

1698

2024.03.01

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

6587

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

2728

2023.08.10

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

4638

2023.08.10

windows查看端口占用情况
windows查看端口占用情况

Windows端口可以认为是计算机与外界通讯交流的出入口。逻辑意义上的端口一般是指TCP/IP协议中的端口,端口号的范围从0到65535,比如用于浏览网页服务的80端口,用于FTP服务的21端口等等。怎么查看windows端口占用情况呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

3399

2023.07.26

查看端口占用情况windows
查看端口占用情况windows

端口占用是指与端口关联的软件占用端口而使得其他应用程序无法使用这些端口,端口占用问题是计算机系统编程领域的一个常见问题,端口占用的根本原因可能是操作系统的一些错误,服务器也可能会出现端口占用问题。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2958

2023.07.27

windows照片无法显示
windows照片无法显示

当我们尝试打开一张图片时,可能会出现一个错误提示,提示说"Windows照片查看器无法显示此图片,因为计算机上的可用内存不足",本专题为大家提供windows照片无法显示相关的文章,帮助大家解决该问题。

1528

2023.08.01

DBeaver怎么导入数据
DBeaver怎么导入数据

DBeaver数据导入专题,整理Excel、CSV、SQL、TXT等常见文件的数据导入方法,涵盖目标数据库选择、数据表创建、字段映射、数据类型设置及导入参数配置等操作,帮助用户将本地文件中的数据写入数据库,并了解批量导入、重复数据处理和导入失败等常见问题的解决方法。

0

2026.11.05

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
dev.java 官方:Learn Java
dev.java 官方:Learn Java

共0课时 | 0人学习

Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn