天天看點

UCS unicode UTF-8 UTF-16 UTF-32

概述

unicode是一套編碼體系; UCS(UCS-2 , UCS-4)是unicode的内碼; UTF-8,UTF-16,UTF-32是unicode的具體實作(計算機内部的處理方式).

一套編碼體系一般包括 字元集, 編碼表和 實作方式三部分。一般像ASCII這樣簡單的編碼系統的編碼映射表與實作方式沒有很嚴格的分界線,即直接用其編碼表示字元,後來複雜的編碼系統考慮到向後相容(相容ASCII)以及存儲效率(UTF-32的效率就很低)等因素,是以在計算機并不直接用字元的編碼号的二進制表示該字元,這也是編碼系統的實作方式的意義之一吧.

UCS

通用字元集(Universal Character Set, UCS)是由ISO制定的ISO 10646(或稱ISO/IEC 10646)标準所定義的标準字元集。UCS-2用兩個位元組編碼,UCS-4用4個位元組編碼。

UCS-4根據最高位為0的最高位元組分成27=128個group。每個group再根據次高位元組分為256個平面(plane)。每個平面根據第3個位元組分為256行 (row),每行有256個碼位(cell)。group 0的平面0被稱作BMP(Basic Multilingual Plane)。如果UCS-4的前兩個位元組為全零,那麼将UCS-4的BMP去掉前面的兩個零位元組就得到了UCS-2。每個平面有216=65536個碼位。Unicode計劃使用了17個平面,一共有17×65536=1114112個碼位。在Unicode 5.0.0版本中,已定義的碼位隻有238605個,分布在平面0、平面1、平面2、平面14、平面15、平面16。其中平面15和平面16上隻是定義了兩個各占65534個碼位的專用區(Private Use Area),分别是0xF0000-0xFFFFD和0x100000-0x10FFFD。所謂專用區,就是保留給大家放自定義字元的區域,可以簡寫為PUA。

unicode

Unicode是國際組織制定的可以容納世界上所有文字和符号的字元編碼方案。Unicode用數字0-0x10FFFF來映射這些字元,最多可以容納1114112個字元,或者說有1114112個碼位。碼位就是可以配置設定給字元的數字。UTF-8、UTF-16、UTF-32都是将數字轉換到程式資料的編碼方案。 在表示一個Unicode的字元時,通常會用“U+”然後緊接着一組十六進制的數字來表示這一個字元。在 基本多文種平面 (英文為 Basic Multilingual Plane,簡寫 BMP。它又簡稱為“零号平面”, plane 0)裡的所有字元,要用四位十六進制數(例如U+4AE0,共支援六萬多個字元);在零号平面以外的字元則需要使用五位或六位十六進制數了。舊版的Unicode标準使用相近的标記方法,但卻有些微的差異:在Unicode 3.0裡使用“U-”然後緊接着八位數,而“U+”則必須随後緊接着四位數。

UTF-8

Unicode轉換為UTF-8時,可以将Unicode二進制從低位往高位取出二進制數字,每次取6位,如上述的二進制就可以分别取出為如下示例所示的格式,前面按格式填補,不足8位用0填補。

按照UTF-8标準, 

(1)所有以0開始的位元組,都與原來的ASCII碼相容,也就是說,0xxxxxxx不需要額外轉換,就是我們平時用的ASCII碼。 

(2)所有以10開始的位元組,都不是每個UNICODE的第一個位元組,都是緊跟着前一位。例如:10110101,這個位元組不可以單獨解析,必須通過前一個位元組來解析,如果前一個也是10開頭,就繼續前嗍。 

(3)所有以11開始的位元組,都表示是UNICODE的第一個位元組,而且後面緊跟着若幹個以10開頭的位元組。如果是110xxxxx(就是最左邊的0的左邊有2個1),代表後面還有1個10xxxxxx;如果是1110xxxx(就是最左邊的0的左邊有3個1),代表後面還有2個10xxxxxx;以此類推,一直到1111110x。 

具體的表格如下: 

1位元組 0xxxxxxx 

2位元組 110xxxxx 10xxxxxx 

3位元組 1110xxxx 10xxxxxx 10xxxxxx 

4位元組 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 

5位元組 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 

6位元組 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 

(很明顯,以11開頭的,最左邊的0左邊有多少個1,那這個UCS的UTF-8的表示長度就有多少個位元組) 

上面是用6個位元組,最多可以表示2 ^ 31個的字元,實際上,隻有UCS-4才有這麼多的字元,對于UCS-2,僅僅有2 ^ 16個字元,隻需要三個位元組就可以,也就是說,隻需要用到下面的格式: 

1位元組 0xxxxxxx 

2位元組 110xxxxx 10xxxxxx 

3位元組 1110xxxx 10xxxxxx 10xxxxxx 

UCS-2和UTF-8的轉換,隻涉及到位運算,不需要像GBK般需要查找代碼表,是以轉換效率很高。 

先來說說UTF-8轉UCS-2: 

(1)對于以0開始的位元組,直接在前面部補一個0的位元組湊成2個位元組(即0xxxxxxx ==> 00000000 0xxxxxxxx); 

(2)對于以110開始(110xxxxx)的位元組,把後面緊跟着的一個10xxxxxx拿過來,首先在高位位元組的左邊補5個零,然後把11個“x”放在右邊(即110xxxxx 10yyyyyy ==> 00000xxx xxyyyyyy); 

(3)對于以1110開始(1110xxxx)的位元組,把後面緊跟着的兩個10xxxxxx拿過來,數一下,一共有16個“x”,沒錯,就是把這16個“x”組成兩個位元組(即1110xxxx 10yyyyyy 10zzzzzz ==> xxxxyyyy yyzzzzzz)。 

在來說說UCS-2轉UTF-8: 

(1)對于不大于0x007F(即00000000 01111111)的,直接把它轉成一個位元組,變成ASCII; 

(2)對于不大于0x07FF(即00000111 11111111)的,轉換成兩個位元組,轉換的時候把右邊的11位分别放到110xxxxx 10yyyyyy裡邊,即00000aaa bbbbbbbb ==> 110aaabb 10bbbbbb 

(3)剩下的回轉換成三個位元組,轉換的時候也是把16個位分别填寫到那三個位元組裡面,即aaaaaaaa bbbbbbbb ==> 1110aaaa 10aaaabb 10bbcccccc 

UTF-16

UTF-16的大尾序和小尾序儲存形式都在用。一般來說,以Macintosh制作或儲存的文字使用大尾序格式,以Microsoft或Linux制作或儲存的文字使用小尾序格式。 為了弄清楚UTF-16檔案的大小尾序,在UTF-16檔案的開首,都會放置一個U+FEFF字元作為Byte Order Mark(UTF-16LE以FF FE代表,UTF-16BE以FE FF代表),以顯示這個文字檔案是以UTF-16編碼,其中U+FEFF字元在UNICODE中代表的意義是ZERO WIDTH NO-BREAK SPACE,顧名思義,它是個沒有寬度也沒有斷字的空白。 UTF-16可看成是UCS-2的父集。在沒有輔助平面字元(surrogate code points)前,UTF-16與UCS-2所指的是同一的意思。但當引入輔助平面字元 後,就稱為UTF-16了。現在若有軟體聲稱自己支援UCS-2編碼,那其實是暗指它不能支援在UTF-16中超過2bytes的字集。對于小于0x10000的UCS碼,UTF-16編碼就等于UCS碼。

UTF-32

UTF-32 (或 UCS-4)是一種将Unicode字元編碼的協定,對每一個Unicode碼位使用恰好32位元。其它的Unicode transformation formats則(如UTF-8)使用不定長度編碼。因為UTF-32對每個字元都使用4位元組,就空間而言,是非常沒有效率的。特别地,非基本多文種平面的字元在大部分檔案中通常很罕見,以緻于它們通常被認為不存在占用空間大小的讨論,使得UTF-32通常會是其它編碼的二到四倍。雖然每一個碼位使用固定長定的位元組看似友善,它并不如其它Unicode編碼使用得廣泛。與UTF-8及UTF-16相比,它有點更容易遭截斷。

本文引用以下文章: http://www.iteye.com/topic/558849