1. 程式人生 > >細說:Unicode, UTF-8, UTF-16, UTF-32, UCS-2, UCS-4

細說:Unicode, UTF-8, UTF-16, UTF-32, UCS-2, UCS-4

字節數 什麽 ans 聯盟 賦值 strong any 江湖 技術分享

轉載自:http://www.cnblogs.com/malecrab/p/5300503.html

==================

1. Unicode與ISO 10646

全世界很多個國家都在為自己的文字編碼,並且互不想通,不同的語言字符編碼值相同卻代表不同的符號(例如:韓文編碼EUC-KR中“???”的編碼值正好是漢字編碼GBK中的“茄憊絹”)。因此,同一份文檔,拷貝至不同語言的機器,就可能成了亂碼,於是人們就想:我們能不能定義一個超大的字符集,它可以容納全世界所有的文字字符,再對它們統一進行編碼,讓每一個字符都對應一個不同的編碼值,從而就不會再有亂碼了。

如果說“各個國家都在為自己文字獨立編碼”是百家爭鳴,那麽“建立世界統一的字符編碼”則是一統江湖,誰都想來做這個武林盟主。早前就有兩個機構試圖來做這個事:
(1) 國際標準化組織(ISO),他們於1984年創建ISO/IEC JTC1/SC2/WG2工作組,試圖制定一份“通用字符集”(Universal Character Set,簡稱UCS),並最終制定了ISO 10646標準。
(2) 統一碼聯盟,他們由Xerox、Apple等軟件制造商於1988年組成,並且開發了Unicode標準(The Unicode Standard,這個前綴Uni很牛逼哦---Unique, Universal, and Uniform)。

1991年前後,兩個項目的參與者都認識到,世界不需要兩個不兼容的字符集。於是,它們開始合並雙方的工作成果,並為創立一個單一編碼表而協同工作。從Unicode 2.0開始,Unicode采用了與ISO 10646-1相同的字庫和字碼;ISO也承諾,ISO 10646將不會替超出U+10FFFF的UCS-4編碼賦值,以使得兩者保持一致。兩個項目仍都獨立存在,並獨立地公布各自的標準。不過由於Unicode這一名字比較好記,因而它使用更為廣泛。

Unicode編碼點分為17個平面(plane),每個平面包含216(即65536)個碼位(code point)。17個平面的碼位可表示為從U+xx0000到U+xxFFFF,其中xx表示十六進制值從0016

到1016,共計17個平面。

2. UTF-32與UCS-4

在Unicode與ISO 10646合並之前,ISO 10646標準為“通用字符集”(UCS)定義了一種31位的編碼形式(即UCS-4),其編碼固定占用4個字節,編碼空間為0x00000000~0x7FFFFFFF(可以編碼20多億個字符)。

UCS-4有20多億個編碼空間,但實際使用範圍並不超過0x10FFFF,並且為了兼容Unicode標準,ISO也承諾將不會為超出0x10FFFF的UCS-4編碼賦值。由此UTF-32編碼被提出來了,它的編碼值與UCS-4相同,只不過其編碼空間被限定在了0~0x10FFFF之間。因此也可以說:UTF-32是UCS-4的一個子集

3. UTF-16與UCS-2

除了UCS-4,ISO 10646標準為“通用字符集”(UCS)定義了一種16位的編碼形式(即UCS-2),其編碼固定占用2個字節,它包含65536個編碼空間(可以為全世界最常用的63K字符編碼,為了兼容Unicode,0xD800-0xDFFF之間的碼位未使用)。例:“漢”的UCS-2編碼為6C49。

但倆個字節並不足以正真地“一統江湖”(a fixed-width 2-byte encoding could not encode enough characters to be truly universal),於是UTF-16誕生了,與UCS-2一樣,它使用兩個字節為全世界最常用的63K字符編碼,不同的是,它使用4個字節對不常用的字符進行編碼。UTF-16屬於變長編碼。

前面提到過:Unicode編碼點分為17個平面(plane),每個平面包含216(即65536)個碼位(code point),而第一個平面稱為“基本多語言平面”(Basic Multilingual Plane,簡稱BMP),其余平面稱為“輔助平面”(Supplementary Planes)。其中“基本多語言平面”(0~0xFFFF)中0xD800~0xDFFF之間的碼位作為保留,未使用。UCS-2只能編碼“基本多語言平面”中的字符,此時UTF-16與UCS-2的編碼一樣(都直接使用Unicode的碼位作為編碼值),例:“漢”在Unicode中的碼位為6C49,而在UTF-16編碼也為6C49。另外,UTF-16還可以利用保留下來的0xD800-0xDFFF區段的碼位來對“輔助平面”的字符的碼位進行編碼,因此UTF-16可以為Unicode中所有的字符編碼。

UTF-16中如何對“輔助平面”進行編碼呢?

Unicode的碼位區間為0~0x10FFFF,除“基本多語言平面”外,還剩0xFFFFF個碼位(並且其值都大於或等於0x10000)。對於“輔助平面”內的字符來說,如果用它們在Unicode中碼位值減去0x10000,則可以得到一個0~0xFFFFF的區間(該區間中的任意值都可以用一個20-bits的數字表示)。該數字的前10位(bits)加上0xD800,就得到UTF-16四字節編碼中的前兩個字節;該數字的後10位(bits)加上0xDC00,就得到UTF-16四字節編碼中的後兩個字節。例如:
技術分享圖片(這個字念啥?^_^)
上面這個漢字的Unicode碼位值為2AEAB,減去0x10000得到1AEAB(二進制值為0001 1010 1110 1010 1011),前10位加上D800得到D86B,後10位加上DC00得到DEAB。於是該字的UTF-16編碼值為D86BDEAB(該值為大端表示,小端為6BD8ABDE)。

4. UTF-8

從前述內容可以看出:無論是UTF-16/32還是UCS-2/4,一個字符都需要多個字節來編碼,這對那些英語國家來說多浪費帶寬啊!(尤其在網速本來就不快的那個年代。。。)由此,UTF-8產生了。在UTF-8編碼中,ASCII碼中的字符還是ASCII碼的值,只需要一個字節表示,其余的字符需要2字節、3字節或4字節來表示。

UTF-8的編碼規則:

(1) 對於ASCII碼中的符號,使用單字節編碼,其編碼值與ASCII值相同(詳見:U0000.pdf)。其中ASCII值的範圍為0~0x7F,所有編碼的二進制值中第一位為0(這個正好可以用來區分單字節編碼和多字節編碼)。

(2) 其它字符用多個字節來編碼(假設用N個字節),多字節編碼需滿足:第一個字節的前N位都為1,第N+1位為0,後面N-1 個字節的前兩位都為10,這N個字節中其余位全部用來存儲Unicode中的碼位值。

字節數UnicodeUTF-8編碼
1 000000-00007F 0xxxxxxx
2 000080-0007FF 110xxxxx 10xxxxxx
3 000800-00FFFF 1110xxxx 10xxxxxx 10xxxxxx
4 010000-10FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

5. 總結

(1) 簡單地說:Unicode屬於字符集,不屬於編碼,UTF-8、UTF-16等是針對Unicode字符集的編碼。

(2) UTF-8、UTF-16、UTF-32、UCS-2、UCS-4對比:

對比UTF-8UTF-16UTF-32UCS-2UCS-4
編碼空間 0-10FFFF 0-10FFFF 0-10FFFF 0-FFFF 0-7FFFFFFF
最少編碼字節數 1 2 4 2 4
最多編碼字節數 4 4 4 2 4
是否依賴字節序

參考:

  • 維基百科:Unicode(中文版)
  • 維基百科:Universal Coded Character Set(中文版)
  • 維基百科:UTF-8(中文版)
  • 維基百科:UTF-16(中文版)
  • 維基百科:UTF-32(中文版)
  • FAQ: UTF-8, UTF-16, UTF-32 & BOM
  • Unicode 8.0 Character Code Charts
  • CJK Unified Ideographs (Han)
  • 阮一峰:字符編碼筆記:ASCII,Unicode和UTF-8
  • UCS vs UTF-8 as Internal String Encoding

本系列文章包括:

  • ANSI是什麽編碼?
  • 漢字編碼:GB2312, GBK, GB18030, Big5
  • 細說:Unicode, UTF-8, UTF-16, UTF-32, UCS-2, UCS-4

轉載請註明出處:http://www.cnblogs.com/malecrab/p/5300503.html

細說:Unicode, UTF-8, UTF-16, UTF-32, UCS-2, UCS-4