概述
代理項(Surrogate),是一種僅在 UTF-16 中用來表示補充字符的方法。在 UTF-16 中,爲補充字符分配兩個 16 位的 Unicode 代碼單元:
- 第一個代碼單元,被稱爲高代理項代碼單元或前導代碼單元;
- 第二個代碼單元,被稱爲低代理項代碼單元或尾隨代碼單元。
這兩個代碼單元組合在一起,就被稱爲代理項對。
相關術語
爲了能更好地理解“代理項”這一概念,就需要先了解相關的 Unicode 術語:1
-
代碼點(Code Point):
- Unicode 代碼空間中的任何值,即從 0 到 10FFFF~16~ 的整數範圍。但並非所有代碼點都分配給編碼字符。
- 一個字符在任何編碼字符集中的值或位置。
- 代碼單元(Code Unit):最小的數位組合,可以表示用於處理或交換的編碼文本的單位。在 Unicode 標準中,UTF-8 編碼格式採用 8 位編碼單元,UTF-16 編碼格式採用 16 位編碼單元,UTF-32 編碼格式採用 32 位編碼單元。
- BMP 字符(BMP Character):位於 BMP(Basic Multilingual Plane,多語種基本面)代碼點的 Unicode 編碼字符。
- BMP 代碼點(BMP Code Point):在 U+0000 到 U+FFFF 範圍內的 Unicode 代碼點。
- 補充字符(Supplementary Character):位於補充代碼點的 Unicode 編碼字符。
- 補充代碼點(Supplementary Code Point):在 U+10000 到 U+10FFFF 範圍內的 Unicode 代碼點。
- 高代理項代碼點(High-Surrogate Code Point):在 U+D800 到 U+DBFF 範圍內的 Unicode 代碼點。
- 高代理項代碼單元(High-Surrogate Code Unit):在 D800~16~ 到 DBFF~16~ 範圍內的 16 位代碼單元,在 UTF-16 中用作代理項對的前導代碼單元(Leading Code Unit)。
- 低代理項代碼點(Low-Surrogate Code Point):在 U+DC00 到 U+DFFF 範圍內的 Unicode 代碼點。
- 低代理項代碼單元(Low-Surrogate Code Unit):在 DC00~16~ 到 DFFF~16~ 範圍內的 16 位代碼單元,在 UTF-16 中用作代理項對的尾隨代碼單元(Trailing Code Unit)。
- 代理項對(Surrogate Pair):由兩個 16 位代碼單元組成,其中第一個是高代理項代碼單元,第二個是低代理項代碼單元。
-
代理項字符(Surrogate Character):用詞不當。這表示一個編碼字符只有一個代理項代碼點,這是不可能的。所以請勿使用這個詞。
特別說明:2
- 高代理項代碼點和低代理項代碼點,僅指定用於此用途(即字面意義所指的用途,不作他用)。
- 高代理項代碼單元和低代理項代碼單元,僅在 UTF-16 中使用。
- 代理項對,僅在 UTF-16 中使用。
釋義
關於代理項的概念,通俗來講,就是爲補充字符找兩個“代理人”。由於補充字符體格壯碩,到了 UTF-16 這個地方就需要佔用兩個 16 位的座位。爲了避免因“佔座糾紛”導致意外發生,就需要爲補充字符找來兩個“代理人”,代替他來佔用兩個座位,這樣就能皆大歡喜了。
- 兩個“代理人”,就是高代理項和低代理項。
- 兩個“代理人”佔用的座位,就是 16 位的高代理項代碼單元和低代理項代碼單元。
- 兩個“代理人”所在的位置,就是高代理項代碼點和低代理項代碼點。
- 兩個“代理人”組合在一起,就是代理項對。
- “代理人”一定是出雙入對的。單身的“代理人”是不能表示補充字符的,只能被稱爲未配對代理項(Unpaired Surrogate)。
代理項僅在 UTF-16 中用來表示補充字符,是指:
- 不在 UTF-8 中使用。補充字符到了 UTF-8 這個地方就需要佔用四個 8 位的座位,而實際給補充字符找的是兩個 16 位的“代理人”,對不上號。
- 不在 UTF-32 中使用。在 UTF-32 這個地方提供的座位,完全符合補充字符的體形,無需再爲其另找“代理人”佔座。
- 不表示 BMP 字符。在補充字符沒有出現時,並沒有“代理人”這一概念,也就是說“代理人”並不是給 BMP 字符找的。
在 Java 中的應用
char 數據類型以及 Character 對象封裝的值,都是基於最初的 Unicode 規範,該規範將字符定義爲固定寬度的 16 位實體。隨着 Unicode 標準的不斷更新,超過 16 位的字符已被允許表示。合法代碼點的範圍已擴展到 U+10FFFF。
在 char 數組、String 類和 StringBuffer 類中,都採用 UTF-16 來表示字符。在這種表示法中,補充字符被表示爲一對 char 值,第一個來自高代理項區間(uD800 - uDBFF),第二個來自低代理項區間(uDC00 - uDFFF)。
因此,char 值可表示 BMP 代碼點、代理項代碼點或 UTF-16 編碼的代碼單元。而所有的 Unicode 代碼點,包括補充代碼點,則用 int 值來表示。int 值中的低 21 位用來表示 Unicode 代碼點,而高 11 位必須爲零。