爲了在面對各種字符編碼的時候不再困惑,因此特此製作本頁面。

Unicode 的故事

Unicode 是一種國際標準字符集,它將世界各種語言的每個字符定義一個唯一的編碼,Unicode 的編碼範圍是 0x0000 - 0x10FFFF ,可以容納一百多萬個字符。Unicode 將這個範圍分成 17 個 面 (plane),每個面有 65536 個字符。第 0 面稱為 基本多言語面 (BMP),包含了最常用的字符,如拉丁字母、漢字、日語假名等。第 1 面到第 16 面稱為 追加面 (supplementary plane),包含了一些古代文字、記號、絵文字等。

重點:Unicode 將每一個字符上序號 (碼點),從 0 1 2 3 4 … 開始。沒錯,就是簡單地編號而已。接下來將 Unicode 編號過的文字稱爲 Unicode 文字。

爲了提高編碼效率,減少儲存空間消耗或者出於其他目的,實際將 Unicode 文字儲存到磁盤文件的時候,會使用「真正的字符編碼規則」,比如 UTF-8、UTF-16、UTF-32 才是真正的字符編碼規則。

UTF-8 是一種變長字符編碼,被定義為將碼點編碼為 1 至 4 個字節,具體取決於碼點數值中有效二進制位的數量。對於英語字母,UTF-8 編碼和 ASCII 碼是相同的。

重點:排在前面的 Unicode 文字會比較常用,這種情況下 UTF-8 使用 1 字節編碼節約儲存空間。稍微不常用的則會分配到 2, 3, 4 字節。UTF-8 的編碼和 Unicode 的編號有一一對應的關係(廢話)。

UTF-16 也是一種變長字符編碼,在 Windows 上比較常用,用於文件名的編碼。這種編碼方式比較特殊, 它將字符編碼成 2 字節 或者 4 字節。對於 Unicode 編號小於 0x10000 的字符, 使用 2 個字節存儲,並且是直接存儲 Unicode 編號,不用進行編碼。

根據 Unicode 官方的 FAQ,UTF-16 會在以下情況下使用 4 個字節:

對於 Unicode 碼在 0x100000x10FFFF 之間的字符,使用 4 個字節存儲,這 4 個字節分成前後兩部分,每個部分各兩個字節,其中,前面兩個字節的前 6 位二進制固定為 110110 ,後面兩個字節的前 6 位二進制固定為 110111, 前後部分各剩余 10 位二進制表示符號的 Unicode 碼減去 0x10000 的結果。

例如,字符 "𠮷" 的 Unicode 碼是 U+20BB7 ,它在 0x100000x10FFFF 之間,所以它的 UTF-16 編碼需要 4 個字節。具體的步驟如下:

  1. U+20BB7 減去 U+10000 ,得到 U+10BB7 ,轉換成二進制是 0001 0000 1011 1011 0111
  2. 將這個二進制數據從中間拆開,每部分各有 10 個位,即:0001 0000 1011 1011 0111
  3. 在每部分的前面加上固定的前綴,即:110110110111 , 得到:110110 0001 0000 10110111 11 1011 0111
  4. 將這兩個二進制數據轉換成十六進制,即:D842 和 DFB7 ,這就是 "𠮷" 的 UTF-16 編碼。