0

0

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

P粉602998670

P粉602998670

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

|

490人浏览过

|

来源于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免费学习笔记(深入)”;

Pliny
Pliny

创建、分享和重新组合AI应用程序

下载
  • 确保传入ZipInputStreamInputStream是**原始、未读取过的**;文件场景下优先用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); }
  • 缓冲区大小选819265536(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工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

智谱清言 - 免费全能的AI助手
智谱清言 - 免费全能的AI助手

智谱清言 - 免费全能的AI助手

相关专题

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

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

246

2023.09.22

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

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

886

2024.03.01

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

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

423

2023.07.18

堆和栈区别
堆和栈区别

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

596

2023.08.10

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

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

720

2023.08.10

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

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

720

2023.08.10

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

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

1256

2023.07.26

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

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

1153

2023.07.27

batoto漫画官网入口与网页版访问指南
batoto漫画官网入口与网页版访问指南

本专题系统整理batoto漫画官方网站最新可用入口,涵盖最新官网地址、网页版登录页面及防走失访问方式说明,帮助用户快速找到batoto漫画官方平台,稳定在线阅读各类漫画内容。

21

2026.02.25

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 3.9万人学习

C# 教程
C# 教程

共94课时 | 10.2万人学习

Java 教程
Java 教程

共578课时 | 72.1万人学习

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

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号