当前位置: 首页 > news >正文

彻底解决 Zip4j 解压中文文件名乱码问题(含混合编码与 Mac 特殊情况)

问题背景:为什么 ZIP 会乱码?

ZIP 是一个“历史包袱很重”的压缩格式,早期并没有规定统一的文件名编码方式。

常见的情况是:

系统常用编码
WindowsGBK
macOS / LinuxUTF-8

因此:

  • Windows 下压的包,用 UTF-8 解压会乱码;

  • macOS 下压的包,用 GBK 解压也会乱码;

  • 而 ZIP 文件内部并没有强制说明使用了哪种编码。

相比之下:

  • 7z → 文件名标准使用 UTF-16,几乎不会乱码;

  • RAR → 新版写了 Unicode 信息,问题较少;

  • ZIP → 完全靠猜。

👉 所以:文件名乱码几乎是 ZIP 独有的老问题。

遇到问题1:出现乱码

原因分析

最开始我写的时候,是这样写的:

val zipFile = ZipFile(file)
zipFile.charset = Charset.forName("GBK")

这意味着无论压缩包来源于哪里,都强制使用 GBK 解码。但如果该文件是 macOS 或 Linux 压缩的(即 UTF-8 编码),文件名就会乱码。

解决方案

思路是先用 GBK 尝试解压,如果检测出乱码,再切换到 UTF-8。

如何判断有没有乱码,我就通过文件名称中是否存在"�"去判断的

当然这种方式后面遇到了别的问题,所以不适合

遇到问题2:混合编码(部分 GBK,部分 UTF-8)

下面两个图片分别展示:同一个压缩包文件使用不同编码的情况

可以看到使用GBK的话,上半部分乱码,下半部分正常

使用UTF-8的话,上半部分正常,下半部分乱码

原因

有些压缩包内部的文件名并不是统一编码的,比如:

  • 一部分文件使用GBK;

  • 一部分文件使用UTF-8

这种情况如果你给整个 zipFile 设置一种编码,就必定会有部分文件乱码。

解决方案:逐文件判断编码

不再给 zipFile 设置统一编码,而是 在读取每个文件头时动态判断编码

通过 fileHeader.isFileNameUTF8Encoded 能判断哪些用UTF-8,哪些用GBK,如果要使用GBK,就从Cp437转换到GBK

修改:删除给zipfile设置的统一编码,改为每个文件头都判断

val zipFile = ZipFile(file)
// 删除下面
// zipFile.charset = Charset.forName("GBK")
private fun getDecodedFileName(fileHeader: FileHeader): String {var result = fileHeader.fileNametry {if (fileHeader.isFileNameUTF8Encoded) {LogUtil.d(TAG, "UTF-8,不用处理")} else {LogUtil.d(TAG, "GBK 编码")result = String(fileHeader.fileName.toByteArray(Charset.forName("Cp437")),Charset.forName("GBK"))}} catch (e: Exception) {LogUtil.e(TAG, "解码文件名时发生错误: ${e.message}")}return result
}

为什么要从Cp437转换到GBK?Zip4j的底层编码是什么样的?

Zip4j库 的解码优先级:

 a. 如果开发者手动设置了编码,则使用开发者设置的编码;

 b. 否则如果文件头带 UTF-8 标志,则使用 UTF-8 解码;

 c. 否则使用 CP437;

上述方案满足了大部分情况,但是满足不了下面的mac操作系统压缩的文件的情况

遇到问题3:macOS 压缩包的特殊情况

下面是同一个mac压缩包里面的文件,使用不同编码的情况

原因

macOS 创建的 ZIP 文件中,虽然文件名实际使用 UTF-8 编码,但它 没有在文件头中设置 UTF-8 标志
这导致:

fileHeader.isFileNameUTF8Encoded == false

从而错误地使用 GBK 解码 → 文件名乱码。

解决方案:检测是否是 Mac 压缩包

我发现几乎所有的mac压缩的压缩包,都会包含一个隐藏文件夹"__MACOSX/",所以我通过判断有没有这个文件夹,来区分是不是Mac操作系统压缩的

判断mac操作系统的方法:

private fun isMacZipFile(zipFile: ZipFile): Boolean {val fileHeaders: List<FileHeader> = zipFile.fileHeadersfor (fileHeader in fileHeaders) {val name = fileHeader.fileNameif (name.startsWith("__MACOSX/")) {return true}}return false
}

所以最终的解决方案如下

最终解决方案


/*** 获取正确编码的文件名,解决文件名乱码问题** 逻辑:* 1. Zip4j库 的解码优先级:*    a. 如果开发者手动设置了编码,则使用开发者设置的编码;*    b. 否则如果文件头带 UTF-8 标志,则使用 UTF-8 解码;*    c. 否则使用 CP437;* 2. macOS 生成的 ZIP 文件未设置 UTF-8 标志,但文件名实际是 UTF-8;* 3. 其他系统根据UTF-8标识设置*/
private fun getDecodedFileName(isMacZipFile: Boolean, fileHeader: FileHeader): String {var result = fileHeader.fileNametry {when {isMacZipFile -> {// mac 的直接设置 UTF_8result = String(fileHeader.fileName.toByteArray(Charset.forName("Cp437")),Charsets.UTF_8)}!fileHeader.isFileNameUTF8Encoded -> {// 非 mac 且 没有 UTF-8 标识:直接使用 GBKresult = String(fileHeader.fileName.toByteArray(Charset.forName("Cp437")),Charset.forName("GBK"))}// 有 UTF-8 标识的,Zip4j 已正确用 UTF-8 处理}} catch (e: Exception) {LogUtil.e(TAG, "解码文件名时发生错误: ${e.message}")}return result
}private fun isMacZipFile(zipFile: ZipFile): Boolean {val fileHeaders: List<FileHeader> = zipFile.fileHeadersfor (fileHeader in fileHeaders) {val name = fileHeader.fileNameif (name.startsWith("__MACOSX/")) {return true}}return false
}

http://www.dtcms.com/a/481789.html

相关文章:

  • 河北农业网站建设公司凡科互动官网登录
  • 企业网站建设的成本构成吉林市网站建设招标
  • git push 报错 push rejected (一文读懂并解决)
  • 从缓存到分库分表:MySQL 高并发海量数据解决方案全解析
  • 苍穹外卖-缓存套餐 Spring Cache day07
  • 垂直电商网站建设方案wordpress主题开发时间
  • 报告工具更新!Word附注一键期末转期初
  • 优化A7M4相机直播图像传输:避免质量损失,实现端到端高保真
  • 平替MongoDB金仓多模数据库在电子证照国产化中的实践与优势
  • AWS WAF 深度体验:全新控制台,开启云原生WAF与CloudFront无缝联防新纪元
  • 【统计字母出现最多次数不分大小写按字典顺序输出】2022-11-9
  • 怎么查自己的网站备案编号本人已履行网站备案信息
  • 电子商务网站建设结论谷歌查询关键词的工具叫什么
  • Ubuntu 安装 SSH,并开启 root 远程登录
  • python学习之路(一)
  • 电源唐大师
  • QT-常用控件(四)-输入类
  • newstar2025 web week1week2题解(少一道)
  • 【C++】vector常用接口的使用
  • ES6 面试题及详细答案 80题 (62-80)-- 类与继承
  • 宁波高质量品牌网站设计厂家网络完全公司排名
  • 网站源码在线提取东莞市网站公司
  • C++中substr()函数详解
  • 乐迪信息:煤矿堆煤隐患难排查?AI摄像机实时监控与预警
  • Deep Dive into LLMs like ChatGPT 学习笔记
  • AI-大模型接入
  • 4.Windows Server 磁盘管理(1)
  • 后端三层架构
  • PyTorch 实现多模型集成与 VGG 在 CIFAR-10 上的应用
  • 网站建设所需费用明细长沙优化官网收费标准