Skip to content

編碼與自動偵測 ​

轉換流程 ​

每個檔案都走同一條路:

檔案轉換流程

  1. 偵測編碼(指定來源編碼時略過)。
  2. 解碼成 Unicode;無效的位元組以 � 取代並計數。
  3. 數字記法:開啟 /cu(或設定中的選項)時,把 &#NNNN;、&#xHHHH; 轉成文字。
  4. 繁簡轉換:依字形設定轉換,見繁簡轉換。
  5. 修正 charset:只對網頁類型的檔案。
  6. 編碼成目標編碼,處理缺字。
  7. 寫入:先寫暫存檔再更名;轉換後位元組完全相同就不寫。

支援的編碼 ​

編碼說明
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):

  1. BOM:EF BB BF 是 UTF-8、FF FE 是 UTF-16 LE、FE FF 是 UTF-16 BE。

  2. 沒有 BOM 的 UTF-16:以英數為主的 UTF-16 文字,每兩個位元組就有一個是 0。其中一邊超過三成是 0、另一邊不到 5% 時判定為 UTF-16。

  3. 二進位檔:其他含有 NUL 位元組的檔案視為二進位檔,自動偵測時略過不轉換。

  4. 7 位元編碼:沒有任何 0x80 以上的位元組時,看到 ESC $ B 這類跳脫序列是 ISO-2022-JP,~{ … ~} 是 HZ,否則就是純 ASCII(當成 UTF-8 處理)。

  5. UTF-8:整段都是合法的 UTF-8 就是 UTF-8。

  6. 雙位元組編碼評分:分別以 Big5、GBK、Shift_JIS、EUC-JP 解碼,計算解出來的字有多少是常用字:

    • Big5 與 GBK 計算 300 個最常用的字——依 Unicode Unihan 的字頻(kHanyuPinlu)排名——以及常用標點,簡體、繁體各一份。
    • 日文看平假名與片假名所佔的比例。
    • 無效的位元組、私用區字元,以及(Shift_JIS 的)大量半形片假名都會扣分。

    評分從第一個非 ASCII 位元組前開始取樣,開頭一大段英數不會把中文擠出取樣範圍。分數最高的勝出。常用字少於 3 個時線索不足,改選無效位元組最少的編碼,並標示為「推測」(圖形介面顯示為橘色的「Big5?」)。

內容太少時

Big5 與 GBK 的位元組範圍大多重疊,中文字只有幾十個的時候可能判斷錯誤。短檔案偵測結果是「猜的」時,請先檢查轉換結果,必要時在「⋯ 更多」指定原本的編碼。

缺字的處理 ​

目標編碼沒有某個字時(例如把「发」輸出成 Big5),依序嘗試:

  1. 代用字:取自 Unicode Unihan 的異體字資料與 OpenCC 的單字對照表。輸出 Big5 時,簡體字換成繁體字(发 → 發)、異體字換成 Big5 有的寫法;輸出 GBK 或 HZ 時,繁體字換成簡體;輸出日文編碼時優先用日本的寫法(发 → 発)。符號換成長得像的符號(① → 1、┏ → ┌),半形片假名換成全形。
  2. 數字記法:網頁類型的檔案寫成 &#NNNN;,瀏覽器會顯示原本的字。
  3. 問號:其他檔案寫成 ?。

轉換結束時會報告有幾個字用了第 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。

數字記法 ​

&#20013;(十進位)與 &#x4E2D;(十六進位)都會還原成「中」。U+0080 以下的不轉換,避免把 &#60;(<)這類字元變回 HTML 語法。

取自 ConvertZ 的對照表僅供個人非商業使用;OpenCC 詞庫為 Apache-2.0 授權。