計算機網絡誕生後,你們慢慢地發現一個問題:一個字節放不下一個字符了!由於須要交流,本地化的文字須要可以被支持。數組
最初的字符集使用7bit來存儲字符,由於那時只須要存下一些英文字母和符號。後來雖然擴展到使用8bit來存儲一個字符了(這種方式被國際標準化組織收錄,成爲ISO8859-1。在字符集發展歷程中國際標準化組織一直髮揮着重要做用。),也仍是沒法存儲諸如中文的字符。網絡
混亂的年代到來了。爲了存儲下本身的文字,各個國家和地區(多爲非拉丁語系的民族,由於這些語種字符數很龐大)各自使用兩個字節即16bit來存放一個字符。他們把首字節的前2^7個位留給一個字節能存下的字符(如英文字母和標點符號),然後的位和後面的字節一塊兒組成適用於本地文字的字符。這中方式一直沿用至今,如GB23十二、GBK(此編碼爲微軟爲簡體中文用戶設計的)、GB18030、BIG5等。使用這種方式有一個問題:不一樣的數值(假如咱們把字符換算成數字)在不一樣的字符集可能有不一樣的意義,甚至使用不一樣字體也會呈現出不一樣的效果!並且從一個字符集到另外一個字符集的轉化也會很是麻煩!字體
標準化一直在進行。爲了解決上述麻煩,各類機構都作出了不一樣的努力。以微軟爲表明的操做系統可能更多的是提供用戶可選擇的語言和區域設置,並使用如CodePage(代碼頁,Windows操做系統對不一樣地區不一樣字符集的支持方式。如GBK爲CP936)來隔離差別,國際標準化組織(ISO)編纂了ISO10646來規範和整合字符集(被成爲通用字符集 Universal Character Set,UCS )。統一碼聯盟(由各個大型企業及組織共同維護)發佈了統一碼(Unicode)項目。ui
起初,UCS和Unicode各自爲政,但1991年先後他們都發現:世界不須要兩個不同的「統一」、「通用」的字符集。因此他們聯合起來維護一個字符集,如今他們的差異大概是發佈新版本時使用什麼字體了-_-。編碼
UCS和Unicode都使用最大32bit來存儲字符,他們(實際上是同樣的,不過仍是區分一下)的碼位(字符數)有1114112個,從0x0到0x0x10FFFF。spa
你們可能會奇怪,32bit最多能夠表示超42億個字符(即從0x0到0xFFFFFFFF),爲何只使用了其中這麼小一部分呢?其實,這裏面還有一些其餘緣由。操作系統
使用32bit來存儲字符看起來是一件一勞永逸的方式,但若是這32bit是定寬的(即任何字符都要使用完這32bit)的話就不可避免的形成空間的浪費,程序效率也會下降!計算機網絡
能不能把UCS(Unicode)設計成「變寬」的呢?聰明的設計師想到了一個主意,他們發明了一種名爲「統一碼轉換格式」即UTF的來將字符對應的數字(可能從小於127至大於100萬不等)轉化爲多個字節來進行存儲。設計
簡單說來,UCS或Unicode只是定義了從0到1114112這些數字各自是什麼字符(而指示界面上該怎麼顯示這個字符則是由「字體」來管理,好比Windows下「微軟雅黑」字體就是這個樣子的(部分):3d
)。而若是從1~4個字節(變寬)還原出這個數字(或字符)就是UTF的事兒了。
好比「漢」字,對應數字爲23383,那麼要使用3字節的UTF8格式字節進行存儲(緣由咱們下面再講),或者1字節的UTF16或1字節的UTF32。
「漢」 UTF8 = {0xE6, 0xB1, 0x89}
UTF16 = {0x6c49}
UTF32 = {0x6c49}(高位補0可省略)
Unicode字符集的劃分大概有兩種:按「單元(Cell)」劃分(Unicode官方文檔是這樣分的)和按「平面(Plane)」劃分。一個單元爲128個字符,一個平面有65536個字符。
咱們一般使用的一個平面取值爲0x0到0xFFFF,這個平面被成爲BMP(Basic Multilingual Plane)即「平面0」。因爲這個平面只是用兩個字節就能夠完整表示,字符集又能夠成爲UCS-2(即便用2字符的「通用字符集」,UCS-4即爲4字節,將UCS-4的高兩位去除即爲UCS-2)。
咱們經常使用的27973個漢字都存放與平面0上,整個Unicode共定義了71226個漢字(Unicode5.0.0),平面2的43253個字符都是漢字。
UTF之間的關係和轉換。上文說道,「漢」字須要3個UTF8字節來存儲,這是由於要符合UTF格式的規範。
一個模版能夠告訴咱們UTF8是怎樣存儲數據的:
Unicode編碼(16進制)
|
UTF-8 字節流(二進制)
|
000000 - 00007F
|
0xxxxxxx
|
000080 - 0007FF
|
110xxxxx 10xxxxxx
|
000800 - 00FFFF
|
1110xxxx 10xxxxxx 10xxxxxx
|
010000 - 10FFFF
|
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
能夠看到,若是使用兩個字節來存儲數據,UTF8最多能夠存儲2^11個字符,最大的數字爲0x7FF即2047,顯然沒法存下數字爲23383的「漢」字。
而經過模版咱們也能夠看出Unicode的最大bit數爲21。
數字向UTF的轉換也很簡單了,把數字換成二進制(不足21位的高位補0),而後填入對應UTF的模版(UTF16和UTF32的模版你們請自行查看,LE和BE區別在於高位和低位的位置,Windows和Linux爲LE,MacOS爲BE)中替換xxxxxxx就好了!很簡單吧。
UTF在文件中的存儲。UTF格式在文件中總有固定文件頭:
UTF編碼
|
Byte Order Mark
|
UTF-8
|
EF BB BF
|
UTF-16LE
|
FF FE
|
UTF-16BE
|
FE FF
|
UTF-32LE
|
FF FE 00 00
|
UTF-32BE
|
00 00 FE FF
|
如「漢」字在文件中的存儲(不包括頭):
Unicode編碼
|
UTF-16LE
|
UTF-16BE
|
UTF32-LE
|
UTF32-BE
|
0x006C49
|
49 6C
|
6C 49
|
49 6C 00 00
|
00 00 6C 49
|
各個系統和語言對Unicode的支持:
Windows NT從底層支持Unicode(不幸的是,Windows 98只是小部分支援Unicode)。先天即被ANSI束縛的C程序設計語言經過對寬字元集的支持來支持Unicode。
Windows底層使用UTF16,Linux使用UTF32(未考證)。
C#和Java支持UTF16且是默認行爲(如字符串天生爲UTF16格式字符數組,Java還可使用'\uxxxx'格式聲明一個字符)。
XML及其子集HTML對UTF16支持很好,爲跨平臺你可使用'&#xxxx;'來聲明一個字符。
(最後編輯時間2013-09-17 20:59:38)