UNICODE 基礎知識

 1
UNICODE 基礎知識
Unicode.org 是一個國際性的組織,致力於使全球各種語言文字在計算機上使用統一的
編碼。經過多年的發展,UNICODE 編碼已經發展到了4.1 的版本。
1. 編碼範圍
早期的UNICODE 版本里,認爲UNICODE 應該是一個固定長度的字符集,用一個16
位的整數來表示一個字符,也就是說一個UNICODE 字符佔用2 個字節的存儲空間。一個
16 位的整數的範圍是0~65535,所以早期版本的UNICODE 最多隻能支持65535個字符。但
是世界上的文字何其多?單單是漢字就不止6 萬個啦。
新版本的UNICODE 爲了容納更多的字符,認爲UNICODE 可以是一個可變長度的字符
集。到目前爲止,UNICODE 字符集的編碼範圍爲0x000000~0x10FFFF,其碼位數量是原來
的17 倍,可以用於表示100 多萬個字符。
2. BMP
目前 UNICODE 字符集的編碼範圍爲0x000000~0x10FFFF,可以分爲17 個平面,每個
平面佔65535個碼位。第0 個平面的碼位範圍是0x0000~0xFFFF,第1 個平面的碼位範圍是
0x10000~0x1FFFF,依此類推。由於UNICODE 的早期發展中,把世界上大量的常用字符都
放在0x0000~0xFFFF 的碼位範圍內,所以大量的常用字符都位於第0 個平面裏,不在第0
個平面裏的字符都是罕見字符。第0 個平面被稱爲基本平面,也就叫做BMP。
3. UCS-2和UCS-4
UCS-2是很早便有的概念,是指UNICODE 固定長度爲2 的雙字節字符集,用兩個字節
來代表一個字符,後來由於雙字節無法表示更多的碼位,所以產生了UCS-4。UCS-4 是指
UNICODE 固定長度爲4 的四字節字符集,用四個字節來代表一個字符。
UCS-2 最初規定爲固定長度爲2 字節的字符集,因爲UCS-2 無法容納碼位大於或者等
於0x10000 的字符,所以被UTF-16 替代。所有碼位大於或等於0x10000 的字符在UCS-2
中都用一個碼位爲0xFFFD 的字符(該字符不可打印,是表示未知字符的意思)代替。UTF-16
可以完全兼容UCS-2,可以把UCS-2 看作是UTF-16 的一個子集。不建議再使用UCS-2,
建議用UTF-16 替代UCS-2。而UCS-4 與UTF-32 完全等價。具體參考後面的UTF-16 和
UTF-32。
4. big-endian和little-endian
內存總是以一個字節爲一個存儲單元的,一個16 位的整數0x1234 在內存裏如何存儲
呢?
在x86的機器裏,第1 個內存單元存放0x34,第2個內存單元存放0x12,這類機器是屬於
little-endian類型的,就是所謂的低字節在前。
在Power PC的機器裏,第1 個內存單元存放0x12,第2 個內存單元存放0x34,這類機器
是屬於big-endian類型的,就是所謂的高字節在前。
5. UTF-8、UTF-16和UTF-32
UTF 是指UNICODE 傳輸格式。UTF-8、UTF-16 和UTF-32 都是UNICODE 的一種表
2
示形式。
(1)UTF-8
UTF-8 是UNICODE 編碼的單字節傳輸格式。UTF-8 可以與ASCII 兼容,所以非常流
行。
UTF-8採用變長編碼方式,一個字符可以是1 個字節,也可以是2、3 或4 個字節,編
碼範圍爲0x000000~0x10FFFF。
編碼規則如下:
1) 碼位範圍是0~127 的字符,只佔用1 個字節,而且編碼與ASCII相同。
2) 碼位範圍大於127 時,首字節有多少個連續的1,就表示該字符佔多少個字節,
首字節的第一個0 之後爲部分爲實際編碼部分,後繼字節總是以標誌位10 開頭,跟在標誌
位10 之後的爲實際編碼部分。
根據上面規則,總結如下:
當要表示的字符的碼位範圍爲0x00~0x7F 的時候就用一個字節:0*******,第一個0
爲標誌位,剩下的空間正好可以表示ASCII 0-127 的內容。
當要表示的字符的碼位範圍爲0x80~0x7FF的時候就用兩個字節:110***** 10******,
第一個字節的110 和第二個字節的10 爲標誌位。
當要表示的字符的碼位範圍爲0x800~0xFFFF的時候就用三個字節:1110**** 10******
10******,和上面一樣,第一個字節的1110和第二、三個字節的10 都是標誌位,大部分常
用漢字都在這個區域。
當要表示的字符的碼位範圍爲0x10000~0x10FFFF 的時候就用四個字節:11110****
10****** 10****** 10******,第一個字節的11110 和第二、三、四個字節的10都是標誌位。
例如:
一個 UNICODE 字符0xFEFF,其UTF-8 的表示爲:EF BB BF。
EF BB BF展開爲二進制則是:11101111 10111011 10111111。第一個字節取1111,第
二個字節取111011,第三個字節取111111,合併起來就是11111110 11111111,正好就是
0xFEFF。
(2)UTF-16
UTF-16,一種通俗的叫法,就是直接叫它作UNICODE。雖然UNICODE 可以表示爲
UTF-8 或者UTF-32,但是很多時候,人們通常所說的UNICODE 一般就是指UTF-16。
UNICODE 發展到今天,UTF-16 可以完全替代UCS-2。
UTF-16 是UNICODE 編碼的雙字節傳輸格式,每一個傳輸單元是2 個字節。UTF-16
必須區分big-endian和little-endian,由此可見,UTF-16 可以分爲UTF-16BE 和UTF-16LE。
UTF-16 採用變長編碼方式,一個字符可以是2 個字節,也可以是4 個字節,編碼範圍
爲0x000000~0x10FFFF。
編碼規則如下:
1) 碼位範圍是0x0000~0xFFFF的字符,只佔用2 個字節,這個區域就是BMP,世
界上大部分常用字符都在這個區域。
2) 碼位範圍是0x10000~0x10FFFF 的字符,需要佔用4 個字節來表示。BMP中預
留出一個區域,這個區域的碼位不表示任何字符,專門作擴展UTF-16 到4 字節使用,這個
區域範圍是0xD800~0xDFFF。這個區域叫代理區域,其中0xD800~0xDBFF 這個範圍叫高
代理,0xDC00~0xDFFF叫低代理。一般高代理在前,低代理在後,兩個代理組成4 字節來
表示一個字符。高代理展開爲二進制的110110** ********,其中前面的110110 爲標誌位。
3
低代理展開爲二進制的110111** ********,其中前面的110111 爲標誌位。高代理取出其低
10 位作爲字符編碼的高10 位,低代理取出其低10 位作爲字符編碼的低10位,這樣就可以
組成一個20位的數字,這個20位的數字再加上0x10000,所得到的和就是字符的編碼,
例如:
在中文裏,有一個非常罕見的字符,其編碼爲0x200B1。UTF-16BE 表示爲D8 40 DC
B1,高代理爲0xD840,低代理爲0xDCB1。高代理展開二進制爲11011000 01000000,低代
理展開二進制爲11011100 10110001。高代理取出其低10 位00 01000000作爲字符編碼的高
10 位,低代理取出其低10 位00 10110001 作爲字符編碼的低10 位,這樣就可以組成一個
20 位的數字01 00000000 10110001,就是十六進制的0x100B1,這個數再加上0x10000,得
到的和爲0x200B1,這個和就是該字符的UNICODE編碼。
(3)UTF-32
UTF-32 是UNICODE 編碼的4 字節傳輸格式,每一個傳輸單元是4 個字節。UTF-32
是固定長度的編碼方式。UTF-32 必須區分big-endian和little-endian,由此可見,UTF-32 可
以分爲UTF-32BE 和UTF-32LE。
UTF-32 非常好,任何字符都可以用一個4 字節的編碼來表示,固定長度使得處理起來
非常方便,唯一的缺點就是比較浪費空間。
6. BOM
BOM是UNICODE中的一個很重要的概念。什麼是BOM?這關係到文本文件的格式。
文本文件,一般以後綴名.txt結尾。所有編程語言的源程序文件,例如*.c、*.cpp、*.h、
*.pas、*.bas、*.java 等等都是文本文件,批處理、Shell 腳本、網頁html 和很多配置文件都
是文本文件。在計算機裏,文本文件無處不在。
一般的文本文件是採用兼容ANSI 的多字節字符集,在Windows 的記事本里,另存爲
的時候選擇編碼爲“ANSI”就是這種類型。不同的國家或地區使用不同的編碼,例如簡體
中文使用GBK/GB18030 編碼,繁體中文使用big-5 編碼,日文使用Shift-JIS 編碼等等。這
類兼容ANSI的多字節字符集使用非常廣泛,但是有個缺點,就是在簡體中文的操作系統裏,
打開big-5 編碼的文本文件會出現亂碼,反之也是如此。
使用 UNICODE字符集的文本文件具有通用性,在不同的操作系統打開時,絕對不會出
現亂碼的現象(前提是該系統必須安裝有對應語言的字體)。使用UNICODE 字符集的文本
文件在比較老的系統,例如Windows 95/98/ME 下面無法顯示。
UNICODE 裏有個編碼爲0xFEFF 的字符,該字符是不可顯示字符,名爲BOM (byte
order mark),主要用於定義字節序,用於區分big-endian和little-endian。一般用於文本文件
的開頭。
由於UNICODE 編碼的文本文件第一個字符一般都是BOM,一般來說,UTF-16LE 以
FF FE 開頭,UTF-16BE 以FE FF開頭,UTF-8以EF BB BF開頭,UTF-32LE 以FF FE 00 00
開頭,UTF-32BE 以00 00 FE FF開頭。
7. 在C/C++中使用UNICODE
在Java 語言中,默認的字符類型就是UTF-16。
在C/C++語言中,char 類型是單字節的,char 數組可以保存與ASCII兼容的字符集,包
括ASCII、GBK、GB18030、big-5、UTF-8 等等。
在 C/C++語言中,還有一種字符類型,叫寬字符類型,類型名爲wchar_t,可以定義2
字節的(UTF-16)字符。字符或者字符串前要加“L”前綴。例如:
4
wchar_t c = L’a’;
wchar_t pStr[] = L”The quick brown dog jumps over the lazy fox”;
8. UTF-8、UTF-16、UTF-32對照表
名稱UTF-8 UTF-16 UTF-16BE UTF-16LE UTF-32 UTF-32BE UTF-32LE
最小代碼點0000 0000 0000 0000 0000 0000 0000
最大代碼點10FFFF 10FFFF 10FFFF 10FFFF 10FFFF 10FFFF 10FFFF
單元大小8位16位16位16位32位32位32位
字節序N/A BOM BE LE BOM BE LE
單字符最小字節1 2 2 2 4 4 4
單字符最大字節4 4 4 4 4 4 4
BOM表示字節序由BOM決定。
BE 表示字節序爲big-endian。
LE 表示字節序爲little-endian。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章