MDA/MDD/TDD/DDD/DDDDDDD
          posts - 536, comments - 111, trackbacks - 0, articles - 0
            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

          Unicode和UTF-8

          Posted on 2009-10-08 17:31 leekiang 閱讀(299) 評論(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字節表示字符串結尾,庫函數strlenstrcpy等等都依賴于這一點,如果字符串用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

          主站蜘蛛池模板: 宣恩县| 斗六市| 忻城县| 淅川县| 尉氏县| 土默特右旗| 侯马市| 德惠市| 八宿县| 和政县| 南岸区| 苗栗市| 湖南省| 呼图壁县| 盐津县| 达拉特旗| 南陵县| 沾益县| 崇明县| 涟源市| 临澧县| 绥宁县| 东阿县| 沈丘县| 高安市| 泰宁县| 棋牌| 格尔木市| 德令哈市| 东源县| 铁岭县| 象山县| 秦皇岛市| 玉树县| 光山县| 九龙城区| 乐业县| 江城| 嘉兴市| 陆河县| 塔城市|