Posted on 2009-10-08 17:31
leekiang 閱讀(296)
評論(0) 編輯 收藏 所屬分類:
java 、
數據結構,算法,基礎
為了統一全世界各國語言文字和專業領域符號(例如數學符號、樂譜符號)的編碼,ISO制定了ISO 10646標準,也稱為UCS(Universal Character Set)。UCS編碼的長度是31位,可以表示231個字符。如果兩個字符編碼的高位相同,只有低16位不同,則它們屬于一個平面(Plane),所以一個平面由216個字符組成。目前常用的大部分字符都位于第一個平面(編碼范圍是U-00000000~U-0000FFFD),稱為BMP(Basic Multilingual Plane)或Plane
0,為了向后兼容,其中編號為0~256的字符和Latin-1相同。UCS編碼通常用U-xxxxxxxx這種形式表示,而BMP的編碼通常用
U+xxxx這種形式表示,其中x是十六進制數字。在ISO制定UCS的同時,另一個由廠商聯合組織也在著手制定這樣的編碼,稱為Unicode,后來兩家聯手制定統一的編碼,但各自發布各自的標準文檔,所以UCS編碼和Unicode碼是相同的。
有了字符編碼,另一個問題就是這樣的編碼在計算機中怎么表示。現在已經不可能用一個字節表示一個字符了,最直接的想法就是用四個字節表示一個字符,這種表示方法稱為UCS-4或UTF-32,UTF是Unicode Transformation Format的縮寫。一方面這樣比較浪費存儲空間,由于常用字符都集中在BMP,高位的兩個字節通常是0,如果只用ASCII碼或Latin-1,高位的三個字節都是0。另一種比較節省存儲空間的辦法是用兩個字節表示一個字符,稱為UCS-2或UTF-16,這樣只能表示BMP中的字符,但BMP中有一些擴展字符,可以用兩個這樣的擴展字符表示其它平面的字符,稱為Surrogate Pair。無論是UTF-32還是UTF-16都有一個更嚴重的問題是和C語言不兼容,在C語言中0字節表示字符串結尾,庫函數strlen
、strcpy
等等都依賴于這一點,如果字符串用UTF-32存儲,其中有很多0字節并不表示字符串結尾,這就亂套了。
UNIX之父Ken Thompson提出的UTF-8編碼很好地解決了這些問題,現在得到廣泛應用。UTF-8具有以下性質:
-
編碼為U+0000~U+007F的字符只占一個字節,就是0x00~0x7F,和ASCII碼兼容。
-
編碼大于U+007F的字符用2~6個字節表示,每個字節的最高位都是1,而ASCII碼的最高位都是0,因此非ASCII碼字符的表示中不會出現ASCII碼字節(也就不會出現0字節)。
-
用于表示非ASCII碼字符的多字節序列中,第一個字節的取值范圍是0xC0~0xFD,根據它可以判斷后面有多少個字節也屬于當前字符的編碼。后面每個字節的取值范圍都是0x80~0xBF,見下面的詳細說明。
-
UCS定義的所有231個字符都可以用UTF-8編碼表示出來。
-
UTF-8編碼最長6個字節,BMP字符的UTF-8編碼最長三個字節。
-
0xFE和0xFF這兩個字節在UTF-8編碼中不會出現。
具體來說,UTF-8編碼有以下幾種格式:
U-00000000?–?U-0000007F:? 0xxxxxxx
U-00000080?–?U-000007FF:? 110xxxxx?10xxxxxx
U-00000800?–?U-0000FFFF:? 1110xxxx?10xxxxxx?10xxxxxx
U-00010000?–?U-001FFFFF:? 11110xxx?10xxxxxx?10xxxxxx?10xxxxxx
U-00200000?–?U-03FFFFFF:? 111110xx?10xxxxxx?10xxxxxx?10xxxxxx?10xxxxxx
U-04000000?–?U-7FFFFFFF:? 1111110x?10xxxxxx?10xxxxxx?10xxxxxx?10xxxxxx?10xxxxxx
第
一個字節要么最高位是0(ASCII字節),要么最高兩位都是1,最高位之后1的個數決定后面有多少個字節也屬于當前字符編碼,例如111110xx,最
高位之后還有四個1,表示后面有四個字節也屬于當前字符的編碼。后面每個字節的最高兩位都是10,可以和第一個字節區分開。這樣的設計有利于誤碼同步,例
如在網絡傳輸過程中丟失了幾個字節,很容易判斷當前字符是不完整的,也很容易找到下一個字符從哪里開始,結果頂多丟掉一兩個字符,而不會導致后面的編碼解
釋全部混亂了。上面的格式中標為x的位就是UCS編碼,最后一種6字節的格式中x位有31個,可以表示31位的UCS編碼,UTF-8就像一列火車,第一
個字節是車頭,后面每個字節是車廂,其中承載的貨物是UCS編碼。UTF-8規定承載的UCS編碼以大端表示,也就是說第一個字節中的x是UCS編碼的高
位,后面字節中的x是UCS編碼的低位。
例如U+00A9(?字符)的二進制是10101001,編碼成UTF-8是11000010 10101001(0xC2 0xA9),但不能編碼成11100000 10000010 10101001,UTF-8規定每個字符只能用盡可能少的字節來編碼。
來源:http://learn.akae.cn/media/apas02.html