ZIP 檔最讓人賭爛的大概就是解壓縮出來的檔名亂碼問題,這在英文系統上面尤其嚴重,只要碰到非 ASCII 的檔名幾乎必死。最近玩政府開放資料,有跨平台的需求,更是被這問題搞到精神耗弱,就順手研究了一下成因及解決方法。
標準怎麼說#
根據官方 .ZIP File Format Specification 的說法:內容檔名在壓縮檔中預設是以 IBM Code Page 437 編碼的;在 language encoding flag (EFS) 被 set 的時候則以 UTF-8 編碼;不採用這兩種以外的編碼方式!
註:各個內容物(檔案、資料夾或 symbolic link)有獨立的 EFS。
殘酷的現實#
壓縮軟體的實作,常常把從系統拿到的路徑直接塞進壓縮檔,然而在不同作業系統、不同語系設定之下,軟體拿到的路徑編碼可能是 Big5、GBK、Shift JIS 等等;EFS 也不是檔名用了 UTF-8 的時候就都會被好好地設起來。用沒有依照標準實作的壓縮軟體壓出來的檔案,在解壓縮的時候就有可能用到錯誤的解碼方式去解碼檔名欄位,造成亂碼。
相容性實驗#
軟體環境 | 同語系檔名 範例 | 異語系檔名 範例 | ||
---|---|---|---|---|
編碼 | EFS | 編碼 | EFS | |
Windows - File Explorer | 系統編碼 | No | 根本不給壓 | |
Windows - 7-Zip | 系統編碼 | No | UTF-8 | Yes |
Windows - Bandizip* | UTF-8 | Yes | UTF-8 | Yes |
OS X - Archive Utility | UTF-8 | No | UTF-8 | No |
OS X - Keka | UTF-8 | Yes | UTF-8 | Yes |
OS X - zip | UTF-8 | No | UTF-8 | No |
Linux - zip | UTF-8 | Yes | UTF-8 | Yes |
嗯……雖然有點慘,但至少沒有設了 EFS 卻又不是 UTF-8 編碼的狀況出現。
軟體環境 | UTF-8 無 EFS | 非 UTF-8 或 Code Page 437 | |
---|---|---|---|
運作情形 | 同語系 | 異語系 | |
Windows - File Explorer | 看不到 | 良好 | 亂碼 |
Windows - 7-Zip 15.14 | 良好 | 良好 | 亂碼 |
Windows - 7-Zip 9.20 | 亂碼 | 良好 | 亂碼 |
Windows - Bandizip* | 良好 | 良好 | 良好 |
OS X - Archive Utility | 良好 | 良好 | 亂碼 |
OS X - Keka | 良好 | 亂碼 | 亂碼 |
OS X - unzip | 良好 | 亂碼 | 亂碼 |
Linux - unzip | 良好 | 亂碼 | 亂碼 |
解決方法?#
壓縮#
環境允許的話盡量避免使用 ZIP 格式。有 non-ASCII 檔名又不得不用的情況下:
解壓縮#
- Windows: Bandizip(但還是有些編碼不支援)
- Cross-Platform: The Unarchiver - 這個厲害!支援不同編碼、編碼偵測、密碼、有 command line 版本,還跨平台!(Debian, Ubuntu, Fedora, MacPorts, Homebrew)
Cross-Platform: 找不到現成的好解法,自己用 Java 寫了個陽春的小 command line tool - Onionzip(目前尚不支援加密檔案)