1.先導概念
編碼格式簡介(ANSI、GBK、GB2312、UTF-8、GB18030和 UNICODE)
2.碼點和代碼單元
-
碼點( code point) 是指與一個編碼表中的某個字符對應的代碼值。
在 Unicode 標准中,碼點采用十六進制書寫,並加上前綴 U+, 例如 U+0041 就是拉丁字母 A 的碼點。Unicode 的碼點可以分成 17 個代碼級別( codeplane)。第一個代碼級別稱為基本的多語言級別( basicmultilingual plane ), 碼點從 U+0000 到 U+FFFF, 其中包括經典的 Unicode 代碼;其余的 16個級另丨〗碼點從 U+10000 到 U+10FFFF , 其中包括一些輔助字符(supplementary character)。
-
UTF-16 編碼采用不同長度的編碼表示所有 Unicode 碼點。在基本的多語言級別中,每個字符用 16 位表示,通常被稱為代碼單元( code unit),而輔助字符采用一對連續的代碼單元進行編碼。
這樣構成的編碼值落人基本的多語言級別中空閑的 2048 字節內, 通常被稱為替代區域(surrogate area) [ U+D800 ~ U+DBFF 用於第一個代碼單兀,U+DC00 ~ U+DFFF 用於第二個代碼單元 ]。這樣設計十分巧妙,我們可以從中迅速地知道一個代碼單元是一個字符的編碼,還是一個輔助字符的第一或第二部分。例如,𝕆是八元數集(http://math.ucr.edu/home/baez/octonions) 的一個數學符號,碼點為 U+1D546, 編碼為兩個代碼單元U+D835 和 U+DD46。(關於編碼算法的具體描述見 http://en.wikipedia.org/wiki/UTF-l6 )
-
在 Java 中,char 類型描述了 UTF-16 編碼中的一個代碼單元。
3.實例驗證
\uD835\uDD46
實際上就是𝕆
,只是在String
里直接顯示為 16 進制
𝕆
是作為一個輔助字符(兩個代碼單元),因而字符串hello\uD835\uDD46
碼點為6,代碼單元為7
/**
* \uD835\uDD46 = 𝕆
* 輸出分別為:7、6
*/
private static void codePoints(){
String sentence = "hello\uD835\uDD46";
System.out.println(sentence.length());
System.out.println(sentence.codePointCount(0,sentence.length()));
}
測試輸出對應的十六進制
/**
* \uD835\uDD46 = 𝕆
* 輸出分別為:d835
* dd46
* 1d546
*/
private static void codePoints(){
String sentence = "\uD835\uDD46";
int length = sentence.length();
for(int i = 0; i < length; i++){
char c = sentence.charAt(i);
System.out.println(Integer.toHexString(c));
}
System.out.println(Integer.toHexString(sentence.codePointAt(0)));
}
4.相關 String 類 API
-
char charAt ( int index )
返回給定位置的代碼單元。除非對底層的代碼單元感興趣, 否則不需要調用這個方法。
-
int codePointAt ( int index ) jdk5.0后加入
返回從給定位置開始的碼點。
-
int offsetByCodePoints( int startlndex, int cpCount) jdk5.0后加入
返回從 startlndex 代碼點開始,位移 cpCount 后的碼點索引。
-
IntStream codePoints() jdk8后加入
將這個字符串的碼點作為一個流返回。調用 toArray 將它們放在一個數組中
-
new String( int[ ] codePoints, int offset, int count) jdk5.0后加入
用數組中從 offset 開始的 count 個碼點構造一個字符串。
-
int codePointCount( int startIndex, int endIndex ) jdk5.0后加入
返回 startlndex 和 endludex-1之間的代碼點數量。沒有配成對的代用字符將計入代碼點。