編碼與自動偵測
轉換流程
每個檔案都走同一條路:
- 偵測編碼(指定來源編碼時略過)。
- 解碼成 Unicode;無效的位元組以
�取代並計數。 - 數字記法:開啟
/cu(或設定中的選項)時,把&#NNNN;、&#xHHHH;轉成文字。 - 繁簡轉換:依字形設定與引擎轉換,見繁簡轉換引擎。
- 修正 charset:只對網頁類型的檔案。
- 編碼成目標編碼,處理缺字。
- 寫入:先寫暫存檔再更名;轉換後位元組完全相同就不寫。
支援的編碼
| 編碼 | 說明 |
|---|---|
| Big5 | 臺灣、香港的傳統繁體編碼(Windows 代碼頁 950) |
| GBK | 簡體中文編碼(代碼頁 936),也收錄繁體字 |
| UTF-8 | 可選擇是否加 BOM |
| UTF-16 LE/BE | 輸出一律加 BOM |
| HZ | 早期電子郵件與新聞群組使用的 7 位元 GB2312 編碼(RFC 1843) |
| Shift_JIS、EUC-JP、ISO-2022-JP | 日文編碼 |
讀寫 Big5、GBK 與日文編碼使用 Firefox 也在用的 encoding_rs(依 WHATWG Encoding 標準);HZ 由 RustZ 自行實作。
自動偵測
偵測依序檢查下列各項(NUL 位元組、是否純英數與 UTF-8 合法性檢查整個檔案;UTF-16 判斷與評分最多取樣 256 KB):
BOM:
EF BB BF是 UTF-8、FF FE是 UTF-16 LE、FE FF是 UTF-16 BE。沒有 BOM 的 UTF-16:以英數為主的 UTF-16 文字,每兩個位元組就有一個是 0。其中一邊超過三成是 0、另一邊不到 5% 時判定為 UTF-16。
二進位檔:其他含有 NUL 位元組的檔案視為二進位檔,自動偵測時略過不轉換。
7 位元編碼:沒有任何 0x80 以上的位元組時,看到
ESC $ B這類跳脫序列是 ISO-2022-JP,~{…~}是 HZ,否則就是純 ASCII(當成 UTF-8 處理)。UTF-8:整段都是合法的 UTF-8 就是 UTF-8。
雙位元組編碼評分:分別以 Big5、GBK、Shift_JIS、EUC-JP 解碼,計算解出來的字有多少是常用字:
- Big5 與 GBK 用的是 ConvertZ 原本的字頻表(144 個最常用的字與標點,繁簡各一份)。
- 日文看平假名與片假名所佔的比例。
- 無效的位元組、私用區字元,以及(Shift_JIS 的)大量半形片假名都會扣分。
評分從第一個非 ASCII 位元組前開始取樣,開頭一大段英數不會把中文擠出取樣範圍。分數最高的勝出。常用字少於 3 個時線索不足,改選無效位元組最少的編碼,並標示為「推測」(圖形介面顯示為橘色的「Big5?」)。
內容太少時
ConvertZ 的說明就提過:中文字少於一百個左右時,Big5 與 GBK 可能判斷錯誤。短檔案偵測結果是「推測」時,請在預覽確認,必要時手動指定來源編碼。
缺字的處理
目標編碼沒有某個字時(例如把「发」輸出成 Big5),依序嘗試:
- 同義字代替:沿用 ConvertZ 的「同義字代替」對照。輸出 Big5 時,簡體字換成繁體字(发 → 發),GBK 擴充區的異體字換成 Big5 有的寫法;輸出 GBK 或 HZ 時,換成簡體或 GBK 有的寫法。半形片假名會換成全形片假名。
- 數字記法:網頁類型的檔案寫成
&#NNNN;,瀏覽器會顯示原本的字。 - 問號:其他檔案寫成
?。
轉換結束時會報告有幾個字用了第 2、3 種方式。
網頁檔的 charset
對網頁類型的檔案,RustZ 會把下列宣告改成目標編碼的名稱:
<meta charset="big5">、<meta http-equiv="Content-Type" content="text/html; charset=big5">,以及程式碼裡的charset=big5。- XML 宣告
<?xml version="1.0" encoding="big5"?>。
只替換原本就是可辨識編碼名稱的值(charset = name 這種變數不會被改)。寫入的名稱:big5、gbk、utf-8、utf-16、shift_jis、euc-jp、iso-2022-jp、hz-gb-2312。
數字記法
中(十進位)與 中(十六進位)都會還原成「中」。U+0080 以下的不轉換,避免把 <(<)這類字元變回 HTML 語法。