細說:Unicode, UTF-8, UTF-16, UTF-32, UCS-2, UCS-4
轉載自: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
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中的碼位值。
字節數 | 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-8、UTF-16等是針對Unicode字符集的編碼。
(2) UTF-8、UTF-16、UTF-32、UCS-2、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 |
是否依賴字節序 | 否 | 是 | 是 | 是 | 是 |
參考:
- 維基百科: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