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

1. Unicode與ISO 10646html

全世界不少個國家都在爲本身的文字編碼,而且互不想通,不一樣的語言字符編碼值相同卻表明不一樣的符號(例如:韓文編碼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)。
spa

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

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

2. UTF-32與UCS-4htm

在Unicode與ISO 10646合併以前,ISO 10646標準爲「通用字符集」(UCS)定義了一種31位的編碼形式(即UCS-4),其編碼固定佔用4個字節,編碼空間爲0x00000000~0x7FFFFFFF(能夠編碼20多億個字符)。blog

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

3. UTF-16與UCS-2utf-8

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

但倆個字節並不足以正真地「一統江湖」(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中的碼位值。

字節數 Unicode UTF-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-八、UTF-16等是針對Unicode字符集的編碼。

(2) UTF-八、UTF-1六、UTF-3二、UCS-二、UCS-4對比:

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

參考:

相關文章
相關標籤/搜索