java解压ZIP 解决中文乱码 (GBK和UTF-8)

本文简书地址

工具使用 : zip4j

GitHub : zip4j

版本 : 2.2.8

Maven :

net.lingala.zip4jgroupId>

zip4jartifactId>

2.2.8version>

dependency>

ZIP解压现状

ZIP格式在不同平台上使用不同软件压缩,大致结果为两类:

1. Windows下使用WinRAR、好压、快压、百度压缩等工具压缩的文件

特点:文件名为GBK编码

2. 使用Linux、MacOS等系统压缩的zip文件

特点:文件名为UTF-8编码

过往解决方案

通过指定解压时的文件名编码类型来解决,最简单粗暴的就是

ZipFile zip = new ZipFile(dest);

//直接指定GBK,反正大多数人用win操作

zip.setFileNameCharset("GBK");

zip.extractAll(Constants.GOODS_ITEM_IMG_PATH);

但是现在用macOS办公的人越来越多,这种写法已经不满足需求了

新解决方案

通过阅读ZIP的协议文档,我们可以发现,Info-ZIP Unicode Path Extra Field (0x7075)

这个额外信息可以解决我们的问题,据笔者测试,WinRAR和百度压缩等使用GBK作为文件编码的压缩软件,

在这个区域会记录文件名的UTF-8编码的名称,但是因为这个字段不是必要字段,文件名使用UTF-8编码的

MacOS归档、Deepin归档等软件不会填充这个信息。

解决方案代码

String extractAll(MultipartFile file) throws Exception {

String path = RECEIVABLE_SHEET_PATH;

if(!new File(path).mkdirs()) {

return "上传文件失败,无法创建临时文件夹";

}

File dest = new File(path + "/"+file.getOriginalFilename());

file.transferTo(dest);

/* 解压 */

try {

ZipFile zip = new ZipFile(dest);

zip.setCharset(Charset.forName("utf-8"));

System.out.println("begin unpack zip file....");

zip.getFileHeaders().forEach(v->{

String extractedFile = getFileNameFromExtraData(v);

try {

zip.extractFile(v, path,extractedFile);

} catch (ZipException e) {

System.out.println("解压失败 :"+extractedFile);

e.printStackTrace();

return;

}

System.out.println("解压成功 :"+extractedFile);

});

System.out.println("unpack zip file success");

} catch (ZipException e) {

if(!new File(path).mkdirs())

return "解压失败";

}

return "success";

}

public static String getFileNameFromExtraData(FileHeader fileHeader) {

if(fileHeader.getExtraDataRecords()!=null){

for (ExtraDataRecord extraDataRecord : fileHeader.getExtraDataRecords()) {

long identifier = extraDataRecord.getHeader();

if (identifier == 0x7075) {

byte[] bytes = extraDataRecord.getData();

ByteBuffer buffer = ByteBuffer.wrap(bytes);

byte version = buffer.get();

assert (version == 1);

int crc32 = buffer.getInt();

System.out.println("使用:fileHeader.getExtraDataRecords() ");

return new String(bytes, 5, buffer.remaining(), StandardCharsets.UTF_8);

}

}

}

System.out.println("使用:fileHeader.getFileName()");

return fileHeader.getFileName();

}

参考ZIP规范资料

Third party mappings commonly used are:

0x07c8 Macintosh

0x2605 ZipIt Macintosh

0x2705 ZipIt Macintosh 1.3.5+

0x2805 ZipIt Macintosh 1.3.5+

0x334d Info-ZIP Macintosh

0x4341 Acorn/SparkFS

0x4453 Windows NT security descriptor (binary ACL)

0x4704 VM/CMS

0x470f MVS

0x4b46 FWKCS MD5 (see below)

0x4c41 OS/2 access control list (text ACL)

0x4d49 Info-ZIP OpenVMS

0x4f4c Xceed original location extra field

0x5356 AOS/VS (ACL)

0x5455 extended timestamp

0x554e Xceed unicode extra field

0x5855 Info-ZIP UNIX (original, also OS/2, NT, etc)

0x6375 Info-ZIP Unicode Comment Extra Field

0x6542 BeOS/BeBox

0x7075 Info-ZIP Unicode Path Extra Field

0x756e ASi UNIX

0x7855 Info-ZIP UNIX (new)

0xa220 Microsoft Open Packaging Growth Hint

0xfd4a SMS/QDOS

-Info-ZIP Unicode Path Extra Field (0x7075):

Stores the UTF-8 version of the file name field as stored in the

local header and central directory header. (Last Revision 20070912)

Value Size Description

----- ---- -----------

(UPath) 0x7075 Short tag for this extra block type ("up")

TSize Short total data size for this block

Version 1 byte version of this extra field, currently 1

NameCRC32 4 bytes File Name Field CRC32 Checksum

UnicodeName Variable UTF-8 version of the entry File Name

Currently Version is set to the number 1. If there is a need

to change this field, the version will be incremented. Changes

may not be backward compatible so this extra field should not be

used if the version is not recognized.

The NameCRC32 is the standard zip CRC32 checksum of the File Name

field in the header. This is used to verify that the header

File Name field has not changed since the Unicode Path extra field

was created. This can happen if a utility renames the File Name but

does not update the UTF-8 path extra field. If the CRC check fails,

this UTF-8 Path Extra Field should be ignored and the File Name field

in the header should be used instead.

The UnicodeName is the UTF-8 version of the contents of the File Name

field in the header. As UnicodeName is defined to be UTF-8, no UTF-8

byte order mark (BOM) is used. The length of this field is determined

by subtracting the size of the previous fields from TSize. If both

the File Name and Comment fields are UTF-8, the new General Purpose

Bit Flag, bit 11 (Language encoding flag (EFS)), can be used to

indicate that both the header File Name and Comment fields are UTF-8

and, in this case, the Unicode Path and Unicode Comment extra fields

are not needed and should not be created. Note that, for backward

compatibility, bit 11 should only be used if the native character set

of the paths and comments being zipped up are already in UTF-8. It is

expected that the same file name storage method, either general

purpose bit 11 or extra fields, be used in both the Local and Central

Directory Header for a file.

参考文献

unzip not correct with cjk filename. #45

Garbled chinese character #73

zip gbk java,java 解压 ZIP 中文 乱码 GBK UTF-8 完美解决方案相关推荐

  1. java读取zip文件名_java无需解压zip压缩包直接读取包内的文件名(含中文)

    java自带了java.util.zip工具可以实现在不解压zip压缩包的情况下读取包内文件的文件名:(注:只能是ZIP格式的,rar我试了不行)代码如下: public static String ...

  2. python rarfile不支持中文路径_python使用zipfile解压文件中文乱码问题

    中文在编程中真实后娘养的,各种坑爹,python3下中文乱码这个问题抓破了头皮,头疼.看了alex的文章,才有种恍然大悟的感觉(链接在底部). 一句话,就是转换成unicode,压缩前是什么编码,使用 ...

  3. linux unzip乱码,Linux 中unzip解压时中文乱码的解决办法

    Linux 中unzip解压时中文乱码的解决办法 Linux 中unzip解压时中文乱码的解决办法 当我们在linux中解压一个含有中文名字的压缩包如"资料.zip"时,如果直接使 ...

  4. Java递归解压zip压缩包

    场景:zip压缩包里面嵌套多层文件夹或者zip压缩包: 使用递归的方式进行解压,解压后得到的目录结构和压缩包目录结构完全一致,非常好用! package com.zhh.api.util;import ...

  5. java 万能解压zip工具类

    项目中有需要解压zip包,但是网上搜了下,工具类过于局限,故整理一个万能的解压zip的工具类.如果大家有更好的方式欢迎交流! 工具类1: /*** 解压文件到指定目录** @param zipFile ...

  6. java解压中文乱码_java解压文件中文乱码怎么处理

    上次利用java自动的java.util.zip.ZipEntry和??java.util.zip.ZipFile来解压zip文件,今天发现程序在读取解压文件时居然报了空指针异常,debug程序后发现 ...

  7. 解决ubuntu中zip解压的中文乱码问题

    在解压windows传过来的zip文件时,才会出现乱码.所以,我用另一个方法解决中文乱码问题. 安装 代码: sudo apt-get install unar 12.04以下或者想编译安装的朋友请参 ...

  8. java代码解压ZIP文件

    1.ZipInputStream类可读取ZIP压缩格式的文件,包括已压缩和未压缩的条目(entry).ZipInputStream类的构造方法如下:ZipInputStream(InputStream ...

  9. windows 解压文件出现乱码 7zip解压文件中文乱码 解决方法

    按照如下教程,更改windows默认编码格式为utf-8之后. https://blog.csdn.net/qq_43780850/article/details/129122210 解压文件时,文件 ...

  10. python使用zipfile解压文件中文乱码问题

    中文在编程中真实后娘养的,各种坑爹,python3下中文乱码这个问题抓破了头皮,头疼.看了alex的文章,才有种恍然大悟的感觉(链接在底部). 一句话,就是转换成unicode,压缩前是什么编码,使用 ...

最新文章

  1. 精读《React PowerPlug 源码》
  2. 柯美smb扫描出现服务器连接错误_柯尼卡美能达363,正确设置了SMB扫描,文件夹也共享了,但扫描后,显示错误为 登录错误,是为什么...
  3. Python入门100题 | 第077题
  4. ios 检测是否联网_秋招|阿里 iOS 五轮面经分享,已收到阿里的意向书
  5. 自治时代:Oracle 公有云离我们很近,自治数据库离我们还远
  6. android AChartEnginee讲解之源码框架解读
  7. python flask接收图像
  8. 01_测试基础知识---功能测试常用方法/正交表的使用
  9. u盘运行linux系统卡住了,从U盘运行Linux操作系统的三种方法
  10. 微信小商店的选型参考及感想
  11. 中维高清监控录像被覆盖故障排除
  12. 智课雅思词汇---八、ject是什么意思
  13. Python 自动化办公之自动识别并点击按钮
  14. 【排序算法】Java版十大经典排序算法实现以及测试结果
  15. Kurento应用开发指南(以Kurento 5.0为模板) 之四:示例教程 一对一视频呼叫
  16. React中文文档之Composition vs Inheritance
  17. html怎么改变li前面的点,CSS定义li前面的小点样式
  18. 天涯共此双11——天猫升级港澳台“购物天堂”
  19. Wide Deep Learning for Recommender Systems【论文记录】
  20. MySQL安装报错:No compatible servers were found.You‘ll need to cancel this wizard and install one

热门文章

  1. phpexcel如何预览数据_可变数据之流水号数据的批量制作与打印
  2. word保存不了磁盘已满_【Word技巧】word使用终极技巧,工程人必会(二)
  3. php员工信息表_一键:快速采集汇总个税专项附加扣除信息
  4. win10自带sftp服务器_用于Windows系统的免费SFTP服务器-Free SFTP Servers及各款软件功能对比...
  5. 在Hive中使用Avro
  6. 《HTML与CSS入门经典(第8版)》——2.5 测试Web内容
  7. Oracle 归档模式的打开及关闭
  8. 如何利用ping命令拥有最佳MTU?
  9. 解决PowerDesigner 错误:Invalid repository user or password!
  10. Linux之父十大名言