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

工具使用 : zip4j

GitHub : zip4j

版本 : 2.2.8

Maven :

net.lingala.zip4j

zip4j

2.2.8

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.

参考文献

java zip解压 中文_java解压ZIP 解决中文乱码 (GBK和UTF-8)相关推荐

  1. java 过滤器 中文_java中Filter过滤器解决中文乱码办法

    java中Filter过滤器解决中文乱码办法 发布时间:2020-04-07 10:19:09 来源:亿速云 阅读:16 作者:小新 这篇文章主要为大家详细介绍了java中Filter过滤器解决中文乱 ...

  2. java web应用 生僻字_Java Web项目中解决中文乱码方法总结

    一.了解常识: 1.UTF-8国际编码,GBK中文编码.GBK包含GB2312,即如果通过GB2312编码后可以通过GBK解码,反之可能不成立; 2.web tomcat:默认是ISO8859-1,不 ...

  3. java aes 中文_java实现AES加密(解决中文解密后乱码问题,解决传输字符串后解密报错的问题)...

    在对安全性要求比较高的报文做加密的时候,算法有很多种,我这里主要用到的就是AES加密算法.由于在国内使用,所以不可避免的要对中文进行加密和解密,而在这个过程中,发现,如果不做处理,很容易会出现中文乱码 ...

  4. java生成pdf不支持中文_java生成pdf以及解决中文中文乱码问题

    [在网上搜了一下iText的东东,简单的整理了一个Demo,解决了中文乱码问题,这里不贴链接了 网上搜一下就行了package com.westdream.test;import java.io.Fi ...

  5. java properties中文_Java读写.properties文件解决中文乱码问题

    一般使用到properties配置文件,一般都是在spring项目里面,直接由框架帮你读,当然,你也得考虑到编码的问题. 但是现在要是要求使用Java直接读写properties文件,就发现很多的问题 ...

  6. java zip 解压 密码_Java解压和压缩带密码的zip文件过程详解

    前言 JDK自带的ZIP操作接口(java.util.zip包,请参看文章末尾的博客链接)并不支持密码,甚至也不支持中文文件名. 为了解决ZIP压缩文件的密码问题,在网上搜索良久,终于找到了winzi ...

  7. java生成unix.z压缩_JAVA压缩 解压缩zip 并解决linux下中文乱码

    1:再压缩前,要设置linux模式, 需要使用第三方ant-1.6.5.jar 如果是文件目录,则 ZipEntry zipEntry=new ZipEntry(basePath + System.g ...

  8. java字符串去掉中文_Java——去除字符串中的中文

    import java.util.regex.Matcher; import java.util.regex.Pattern; public class RemoveStrChinese { priv ...

  9. 详解Spring MVC请求参数类型,解决中文乱码问题,自定义类型转换器,Spring MVC相关注解

    #SpringMVC SpringMVC请求 简单类型 简单类型包括:基本类型,基本类型的包装类型,字符串 编写Controller @RequestMapping("/param" ...

最新文章

  1. HotSpot模板解释器目标代码生成过程源码分析
  2. 解决无扬声器(无喇叭)的HDMI接口显示屏声音问题
  3. 【Android 应用开发】Android 图表绘制 achartengine 示例解析
  4. 用Artifactory管理内部Maven仓库
  5. SAP UI5 应用开发教程的学习目录
  6. python中的split函数的用法实例_python中的split()函数的用法
  7. Java Swing实现局域网QQ
  8. 用excel表格解线性方程组
  9. 再爆hzhost6.5虚拟主机管理系统的SQL注入漏洞3
  10. 摄影后期人像高端摄影后期PS修图技巧
  11. Labview筛选符合条件的数据
  12. 金万维未找到服务器信息,域名解析失败原因和问题排查方法
  13. nubia/努比亚Z5Sn(32GB) root教程_方法
  14. VSPD虚拟串口使用
  15. Mott-insulator transitions in BEC
  16. python 抓包秒杀_Python 爬虫,推荐一款简单的抓包工具(续)
  17. Shader学习之Cg语言三(Cg表达式与控制语句)
  18. 论所谓“适合自己的方法”
  19. byte转word类型。
  20. 超级兔子魔法设置正式版

热门文章

  1. java date dec_java – 将日期从“2009-12 Dec”格式转换为“31-DEC-2009”
  2. 网络安全学习笔记——DNS漏洞
  3. RT-Thread ENV工具 pkgs --upgrade 报错:open .config failed
  4. 天线要设计为四分之一波长的原因
  5. 使用VS+VisualGDB编译Linux版本RCF
  6. 计算机中的二进制实验报告,大学计算机-实验报告一.doc
  7. 使用spark.streaming.kafka.consumer.poll.ms和reconnect.backoff.ms解决spark streaming消费kafka时任务不稳定的问题
  8. 化模糊为清晰的图片清晰术:动手尝试修复模糊老照片
  9. R语言简单应用掷骰子游戏
  10. 演示4:python的币值转换-含tkinter