半完美解决 zip 文件中中文文件名乱码的问题

2

Comments

前一段由于收了某个 zip 文件,用 Ubuntu 自带的归档管理器打开,哎呦,那真不是一般的蛋疼……因为里面全是中文文件名,那个乱码啊……

于是我就下决心要解决这个问题。

虽然我的系统还在 9.10,但看到网上一篇文章教人如何在 10.04 中解决这个问题,我就了解了,这个问题至今没有解决。那么什么叫做“半完美”呢?大概意思就是说,对我来说差不多完美了,不过还是很可能出问题的……

命令行方法

一般的方法是利用命令行的方式:

1
2
LANG=C 7z x xxxx.zip
convmv -f gbk -t utf8 *

用这个方法,我就写了一个 unzip 的小脚本:

1
2
#! /bin/sh
LANG=C /usr/lib/p7zip/7z x -y "$1" | sed -n 's/^Extracting  //p' | sed '1!G;h;$!d' | xargs convmv -f gbk -t utf8 --notest >\dev\null 2>\dev\null

功能就是 unzip xxxx.zip 能够自动转码。内部机理我就不详细解释了,其实也不复杂。而且由于我不大会用 sed,所以用了两段,但我相信是不需要的。

不过这个不完美,为什么呢?因为这样我用归档管理器打开还是乱码,根本没有解决任何问题!

我的半完美方法

于是我就开始打 7z 程序的主意……当然最后是成功了的,这里先放对比图哈~

现在做了一个 Ubuntu 的 patch 出来,需要的童鞋可以在这里下载:p7zip_9.04~dfsg.1-1chinese.diff.gz (1.1KB)。不要看是 9.04 的,据我观察在 lucid 当中版本号还是这个,p7zip 一直没有变化过……

下载完以后再找个目录获取 p7zip 的代码:

1
apt-get source p7zip-full

注意这里不需要 sudo 权限,因为获取源代码是自由的~

然后把刚才下载的那个 patch 文件放进代码目录,一般来说应该是 p7zip-9.04~dfsg.1 目录。然后执行下面代码:

1
gzip -cd p7zip_9.04~dfsg.1-1chinese.diff.gz | patch -p1

然后就常规了:

1
2
make all3
sudo make install

需要注意的是,这里安装完以后并没有覆盖原来 p7zip 包的文件,但是放在了一个更优先访问的位置,所以以后执行 7z 相关的操作都会访问这里安装的。

由于编译需要很长很长时间,所以我这里编译好了一份:p7z-bin.tar.bz2 (1.6M),是 Ubuntu i386 版本的,如果你也是 i386 的就可以直接下载这个,用里面的程序覆盖掉 /usr/lib/p7zip/ 里面的程序,就可以了~

当然,最好把相同功能的 unzip 先卸掉……

现在,在系统里面以任何方式查看或解压任何 zip,理论上应该不会出现乱码了,我想是这样……

解决思路

好了,对于只想解决问题的人,看到这里就够了。现在我想写写如何做到的。

我看了一下 p7zip 的代码,还算是条理相当清晰,其中最重要的部分是 ZipIn.cpp 里面的 ReadFileName 函数,我在里面读取文件名之后插入了一段使用 iconv 函数转换编码的代码。

其后我发现不能这样简单的转换编码,因为在 Linux 下面打包的 zip 文件,文件名是用 utf8 而非 gb18030 储存的,这样在转换的时候反而出现乱码。我观察了一下,WinRAR 能够正常读出这些文件名的编码。因此我又在另外一些相关的函数中加入了判断打包平台的代码,以确认是否要转换编码。

此外,由于 gb18030 是硬编码进去的,显然不太好,但我暂时想不出什么更好的解决方法。我想这对于目前的国内自己用应该是足够了,不过考虑到开源软件一向喜欢的国际化,我就实在没什么办法了……如果有人有办法,请一定告诉我!

不过为了平衡,我最后在 config.h 里面加入了 MY_ENCODING 宏,这样可以修改这个以改变硬编码的文字编码值,也算是一点点努力吧……

一点抱怨

由于是在上网本上做的,而且我不想折磨我可怜的 SSD 或者移动硬盘,因此我不得不在内存盘中进行编译。每次都是心惊胆战的,生怕内存不够用开始吃交换区……当然最后还是没有……

话说 Windows 混乱的内码转换害死人啊……

参考资料

2 Responses to “半完美解决 zip 文件中中文文件名乱码的问题”

  1. delectate Says:
    2010年6月22日 19:28 回复

    win的编码问题真的是很大,又是mp3,又是zip,最后txt还给你乱一下……

    不知道编译smplayer能不能解决rmvb标题栏乱码 :)

Leave a Reply