UTF8並不算是一種電腦編碼,而是一種儲存和傳送的格式,如前所述,每一個Unicode/UCS字符都以 2或4個bytes來儲存,看看如下的比較:
以"I am Chinese"爲例
用ANSI儲存:12 Bytes
用Unicode/UCS2儲存:24 Bytes + 2 Bytes(header)
用UCS4儲存:48 Bytes + 4 Bytes(header)
以"我是中國人"爲例
用ANSI儲存:10 Bytes
用Unicode/UCS2儲存:10 Bytes + 2 Bytes(header)
用UCS4儲存:20 Bytes + 4 Bytes(header)
因而可知直接以Unicode/UCS的原始形式來儲存是一種極大的浪費,並且也不利於互聯網的傳輸(中文稍爲合算一點^_^)。
有見及此,Unicode/UCS的壓縮形式--UTF8出現了,套用官方網站的首句話『UTF-8 stands for Unicode Transformation Format-8. It is an octet (8-bit) lossless encoding of Unicode characters.』,因爲UTF也適用於編碼UCS,故亦可稱爲『UCS transformation formats (UTF)』
UTF8是以8bits即1Bytes爲編碼的最基本單位,固然也能夠有基於16bits和32bits的形式,分別稱爲UTF16和UTF32,但目前用得很少,而UTF8則被普遍應用在文件儲存和網絡傳輸中。
編碼原理
先看這個模板:
UCS-4 range (hex.) UTF-8 octet sequence (binary)
0000 0000-0000 007F 0xxxxxxx
0000 0080-0000 07FF 110xxxxx 10xxxxxx
0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-001F FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
0020 0000-03FF FFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
0400 0000-7FFF FFFF 1111110x 10xxxxxx ... 10xxxxxx
編碼步驟:
1) 首先肯定須要多少個8bits(octets)
2) 按照上述模板填充每一個octets的高位bits
3) 把字符的bits填充至x中,字符順序:低位→高位,UTF8順序:最後一個octet的最末位x→第一個octet最高位x
4) 解碼的原理同樣。
實例:(留意每一個bit的顏色,粗體字爲模板內容)
UCS-4 UTF-8
HEX BIN Bytes BIN HEX Bytes
0000 000A 00001010 4 00001010 0A 1
0000 0099 10011001 4 11000010 10011001 C2 99 2
0000 8D99 10001101 10011001 4 11101000 10110110 10011001 E8 B6 99 3
不知你們看懂了沒有,其實不懂也無所謂,反正又不用本身算,程式能夠徹底代勞。
以UTF8格式儲存的文件檔首標識爲EF BB BF。
效率
從上述編碼原理中得出的結論是:
1.每一個英文字母、數字所佔的空間爲1 Byte;
2.泛歐語系、斯拉夫語字母佔2 Bytes;
3.漢字佔3 Bytes。
因而可知UTF8對英文來講是個很是誘人的方案,但對中文來講則不太合算,不管用ANSI仍是 Unicode/UCS2來編碼都只用2 Bytes,但用UTF8則須要3 Bytes。
如下是一些統計資料,顯示用UTF8來儲存文件每一個字符所需的平均字節:
1.拉丁語系平均用1.1 Bytes;
2.希臘文、俄文、阿拉伯文和希伯萊文平均用1.7 Bytes;
3.其餘大部份文字如中文、日文、韓文、Hindi(北印度語)用約3 Bytes;
4.用超過4 Bytes的都是些很是少用的文字符號。
Unicode(統一碼、萬國碼、單一碼)是一種在計算機上使用的字符編碼。它爲每種語言中的每一個字符設定了統一而且惟一的二進制編碼,以知足跨語言、跨平臺進行文本轉換、處理的要求。1990年開始研發,1994年正式公佈。隨着計算機工做能力的加強,Unicode也在面世以來的十多年裏獲得普及。
Unicode 是基於通用字符集(Universal Character Set)的標準來發展,而且同時也以書本的形式(The Unicode Standard,目前第五版由Addison-Wesley Professional出版,ISBN-10: 0321480910)對外發表。
2006年6月的最新版本的 Unicode 是 2005年3月31日推出的Unicode 4.1.0 。另外,5.0 Beta已於2005年12月12日推出,以供各會員評價。
[編輯本段]Unicode 的編碼和實現
大概來講,Unicode 編碼系統可分爲編碼方式和實現方式兩個層次。
1.編碼方式
Unicode是國際組織制定的能夠容納世界上全部文字和符號的字符編碼方案。Unicode用數字0-0x10FFFF來映射這些字符,最多能夠容納1114112個字符,或者說有1114112個碼位。碼位就是能夠分配給字符的數字。UTF-八、UTF-1六、UTF-32都是將數字轉換到程序數據的編碼方案。
Unicode字符集能夠簡寫爲UCS(Unicode Character Set)。早期的Unicode標準有UCS-二、UCS-4的說法。UCS-2用兩個字節編碼,UCS-4用4個字節編碼。UCS-4根據最高位爲0的最高字節分紅2^7=128個group。每一個group再根據次高字節分爲256個平面(plane)。每一個平面根據第3個字節分爲256行 (row),每行有256個碼位(cell)。group 0的平面0被稱做BMP(Basic Multilingual Plane)。將UCS-4的BMP去掉前面的兩個零字節就獲得了UCS-2。
每一個平面有2^16=65536個碼位。Unicode計劃使用了17個平面,一共有17*65536=1114112個碼位。在Unicode 5.0.0版本中,已定義的碼位只有238605個,分佈在平面0、平面一、平面二、平面1四、平面1五、平面16。其中平面15和平面16上只是定義了兩個各佔65534個碼位的專用區(Private Use Area),分別是0xF0000-0xFFFFD和0x100000-0x10FFFD。所謂專用區,就是保留給你們放自定義字符的區域,能夠簡寫爲PUA。
平面0也有一個專用區:0xE000-0xF8FF,有6400個碼位。平面0的0xD800-0xDFFF,共2048個碼位,是一個被稱做代理區(Surrogate)的特殊區域。代理區的目的用兩個UTF-16字符表示BMP之外的字符。在介紹UTF-16編碼時會介紹。
如前所述在Unicode 5.0.0版本中,238605-65534*2-6400-2408=99089。餘下的99089個已定義碼位分佈在平面0、平面一、平面2和平面14上,它們對應着Unicode目前定義的99089個字符,其中包括71226個漢字。平面0、平面一、平面2和平面14上分別定義了52080、341九、43253和337個字符。平面2的43253個字符都是漢字。平面0上定義了27973個漢字。
2.實現方式
在Unicode中:漢字「字」對應的數字是23383。在Unicode中,咱們有不少方式將數字23383表示成程序中的數據,包括:UTF-八、UTF-1六、UTF-32。UTF是「UCS Transformation Format」的縮寫,能夠翻譯成Unicode字符集轉換格式,即怎樣將Unicode定義的數字轉換成程序數據。例如,「漢字」對應的數字是0x6c49和0x5b57,而編碼的程序數據是:
BYTE data_utf8[] = {0xE6, 0xB1, 0x89, 0xE5, 0xAD, 0x97}; // UTF-8編碼
WORD data_utf16[] = {0x6c49, 0x5b57}; // UTF-16編碼
DWORD data_utf32[] = {0x6c49, 0x5b57}; // UTF-32編碼
這裏用BYTE、WORD、DWORD分別表示無符號8位整數,無符號16位整數和無符號32位整數。UTF-八、UTF-1六、UTF-32分別以BYTE、WORD、DWORD做爲編碼單位。「漢字」的UTF-8編碼須要6個字節。「漢字」的UTF-16編碼須要兩個WORD,大小是4個字節。「漢字」的UTF-32編碼須要兩個DWORD,大小是8個字節。根據字節序的不一樣,UTF-16能夠被實現爲UTF-16LE或UTF-16BE,UTF-32能夠被實現爲UTF-32LE或UTF-32BE。下面介紹UTF-八、UTF-1六、UTF-3二、字節序和BOM。
UTF-8
UTF-8以字節爲單位對Unicode進行編碼。從Unicode到UTF-8的編碼方式以下:
Unicode編碼(16進制) ║ UTF-8 字節流(二進制)
000000 - 00007F ║ 0xxxxxxx
000080 - 0007FF ║ 110xxxxx 10xxxxxx
000800 - 00FFFF ║ 1110xxxx 10xxxxxx 10xxxxxx
010000 - 10FFFF ║ 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
UTF-8的特色是對不一樣範圍的字符使用不一樣長度的編碼。對於0x00-0x7F之間的字符,UTF-8編碼與ASCII編碼徹底相同。UTF-8編碼的最大長度是4個字節。從上表能夠看出,4字節模板有21個x,便可以容納21位二進制數字。Unicode的最大碼位0x10FFFF也只有21位。
例1:「漢」字的Unicode編碼是0x6C49。0x6C49在0x0800-0xFFFF之間,使用用3字節模板了:1110xxxx 10xxxxxx 10xxxxxx。將0x6C49寫成二進制是:0110 1100 0100 1001, 用這個比特流依次代替模板中的x,獲得:11100110 10110001 10001001,即E6 B1 89。
例2:Unicode編碼0x20C30在0x010000-0x10FFFF之間,使用用4字節模板了:11110xxx 10xxxxxx 10xxxxxx 10xxxxxx。將0x20C30寫成21位二進制數字(不足21位就在前面補0):0 0010 0000 1100 0011 0000,用這個比特流依次代替模板中的x,獲得:11110000 10100000 10110000 10110000,即F0 A0 B0 B0。
UTF-16
UTF-16編碼以16位無符號整數爲單位。咱們把Unicode編碼記做U。編碼規則以下:
若是U<0x10000,U的UTF-16編碼就是U對應的16位無符號整數(爲書寫簡便,下文將16位無符號整數記做WORD)。
若是U≥0x10000,咱們先計算U'=U-0x10000,而後將U'寫成二進制形式:yyyy yyyy yyxx xxxx xxxx,U的UTF-16編碼(二進制)就是:110110yyyyyyyyyy 110111xxxxxxxxxx。
爲何U'能夠被寫成20個二進制位?Unicode的最大碼位是0x10ffff,減去0x10000後,U'的最大值是0xfffff,因此確定能夠用20個二進制位表示。例如:Unicode編碼0x20C30,減去0x10000後,獲得0x10C30,寫成二進制是:0001 0000 1100 0011 0000。用前10位依次替代模板中的y,用後10位依次替代模板中的x,就獲得:1101100001000011 1101110000110000,即0xD843 0xDC30。
按照上述規則,Unicode編碼0x10000-0x10FFFF的UTF-16編碼有兩個WORD,第一個WORD的高6位是110110,第二個WORD的高6位是110111。可見,第一個WORD的取值範圍(二進制)是11011000 00000000到11011011 11111111,即0xD800-0xDBFF。第二個WORD的取值範圍(二進制)是11011100 00000000到11011111 11111111,即0xDC00-0xDFFF。
爲了將一個WORD的UTF-16編碼與兩個WORD的UTF-16編碼區分開來,Unicode編碼的設計者將0xD800-0xDFFF保留下來,並稱爲代理區(Surrogate):
D800-DB7F ║ High Surrogates ║ 高位替代
DB80-DBFF ║ High Private Use Surrogates ║ 高位專用替代
DC00-DFFF ║ Low Surrogates ║ 低位替代
高位替代就是指這個範圍的碼位是兩個WORD的UTF-16編碼的第一個WORD。低位替代就是指這個範圍的碼位是兩個WORD的UTF-16編碼的第二個WORD。那麼,高位專用替代是什麼意思?咱們來解答這個問題,順便看看怎麼由UTF-16編碼推導Unicode編碼。
若是一個字符的UTF-16編碼的第一個WORD在0xDB80到0xDBFF之間,那麼它的Unicode編碼在什麼範圍內?咱們知道第二個WORD的取值範圍是0xDC00-0xDFFF,因此這個字符的UTF-16編碼範圍應該是0xDB80 0xDC00到0xDBFF 0xDFFF。咱們將這個範圍寫成二進制:
1101101110000000 11011100 00000000 - 1101101111111111 1101111111111111
按照編碼的相反步驟,取出高低WORD的後10位,並拼在一塊兒,獲得
1110 0000 0000 0000 0000 - 1111 1111 1111 1111 1111
即0xe0000-0xfffff,按照編碼的相反步驟再加上0x10000,獲得0xf0000-0x10ffff。這就是UTF-16編碼的第一個WORD在0xdb80到0xdbff之間的Unicode編碼範圍,即平面15和平面16。由於Unicode標準將平面15和平面16都做爲專用區,因此0xDB80到0xDBFF之間的保留碼位被稱做高位專用替代。
UTF-32
UTF-32編碼以32位無符號整數爲單位。Unicode的UTF-32編碼就是其對應的32位無符號整數。
字節序
根據字節序的不一樣,UTF-16能夠被實現爲UTF-16LE或UTF-16BE,UTF-32能夠被實現爲UTF-32LE或UTF-32BE。例如:
Unicode編碼 ║ UTF-16LE ║ UTF-16BE ║ UTF32-LE ║ UTF32-BE
0x006C49 ║ 49 6C ║ 6C 49 ║ 49 6C 00 00 ║ 00 00 6C 49
0x020C30 ║ 43 D8 30 DC ║ D8 43 DC 30 ║ 30 0C 02 00 ║ 00 02 0C 30
那麼,怎麼判斷字節流的字節序呢?Unicode標準建議用BOM(Byte Order Mark)來區分字節序,即在傳輸字節流前,先傳輸被做爲BOM的字符"零寬無中斷空格"。這個字符的編碼是FEFF,而反過來的FFFE(UTF-16)和FFFE0000(UTF-32)在Unicode中都是未定義的碼位,不該該出如今實際傳輸中。下表是各類UTF編碼的BOM:
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 環境
在非 Unicode 環境下,因爲不一樣國家和地區採用的字符集不一致,極可能出現沒法正常顯示全部字符的狀況。微軟公司使用了代碼頁(Codepage)轉換表的技術來過渡性的部分解決這一問題,即經過指定的轉換表將非 Unicode 的字符編碼轉換爲同一字符對應的系統內部使用的 Unicode 編碼。能夠在「語言與區域設置」中選擇一個代碼頁做爲非 Unicode 編碼所採用的默認編碼方式,如936爲簡體中文GBK,950爲正體中文Big5(皆指PC上使用的)。在這種狀況下,一些非英語的歐洲語言編寫的軟件和文檔極可能出現亂碼。而將代碼頁設置爲相應語言中文處理又會出現問題,這一狀況沒法避免。從根本上說,徹底採用統一編碼纔是解決之道,但目前上沒法作到這一點。
代碼頁技術如今普遍爲各類平臺所採用。UTF-7 的代碼頁是65000,UTF-8 的代碼頁是65001。
[編輯本段]XML 和 Unicode
XML及其子集HTML採用UTF-8做爲標準字集,理論上咱們能夠在各類支持XML標準的瀏覽器上顯示任何地區文字的網頁,只要電腦自己安裝有合適的字體便可。能夠利用&#nnn;的格式顯示特定的字符。nnn表明該字符的十進制 Unicode 代碼。若是採用十六進制代碼,在編碼以前加上x字符便可。但部分舊版本的瀏覽器可能沒法識別十六進制代碼。
然而部分因爲 Unicode 版本發展緣由,不少瀏覽器只能顯示 UCS-2 完整字符集也即如今使用的 Unicode 版本中的一個小子集。下表能夠檢驗您的瀏覽器怎樣顯示各類各樣的 Unicode 代碼:
代碼 字符標準名稱 (英語) 在瀏覽器上的顯示
A&#大寫拉丁字母"A" A
&#szlig; 小寫拉丁字母"Sharp S" ß
&#thorn; 小寫拉丁字母"Thorn" þ
Δ大寫希臘字母"Delta" Δ
Й 大寫斯拉夫字母"Short I" Й
?希伯來字母"Qof" ?
?阿拉伯字母 "Meem" ?
?泰文數字 7 ?
?埃塞俄比亞音節文字"Qha" ?
あ日語平假名 "A" あ
ア日語片假名 "A" ア
葉簡體漢字 "葉" 葉
葉 繁體漢字 "葉" 葉
?韓國音節文字 " Yeob" ?
[編輯本段]輸入Unicode
除了輸入法外,操做系統會提供幾種方法輸入Unicode。像是Windows 2000以後的Windows系統就提供一個可點擊的表。例如在Microsoft Word或者金山WPS之下,按下 Alt 鍵不放,輸入 0 和某個字符的 Unicode 編碼(十進制),再鬆開 Alt 鍵便可獲得該字符,如Alt + 033865會獲得Unicode字符「葉」(繁體)。另外按Alt + X 組合鍵,MS Word 也會將光標前面的字符同其十六進制的四位 Unicode 編碼進行互相轉換。
Unicode 編碼表反彈
0000-0FFF 8000-8FFF 10000-10FFF 20000-20FFF 28000-28FFF
1000-1FFF 9000-9FFF 21000-21FFF 29000-29FFF
2000-2FFF A000-AFFF 22000-22FFF 2A000-2AFFF
3000-3FFF B000-BFFF 23000-23FFF
4000-4FFF C000-CFFF 1D000-1DFFF 24000-24FFF 2F000-2FFFF
5000-5FFF D000-DFFF 25000-25FFF
6000-6FFF E000-EFFF 26000-26FFF
7000-7FFF F000-FFFF 27000-27FFF E0000-E0FFF
Unicode 目前已經有5.0版本。世界上有一大批計算機、語言學等科學家專門研究Unicode,到了如今Unicode標準已經不單是一個編碼標準,仍是記錄人類語言文字資料的一個巨大的數據庫,同時從事人類文化遺產的發掘和保護工做。
對於中文而言,Unicode 16編碼裏面已經包含了GB18030裏面的全部漢字(27484個字),目前Unicode標準準備把康熙字典的全部漢字放入到Unicode 32bit編碼中。
簡單地說,Unicode擴展自ASCII字元集。在嚴格的ASCII中,每一個字元用7位元表示,或者電腦上廣泛使用的每字元有8位元寬;而Unicode使用全16位元字元集。這使得Unicode可以表示世界上全部的書寫語言中可能用於電腦通信的字元、象形文字和其餘符號。Unicode最初打算做爲ASCII的補充,可能的話,最終將代替它。考慮到ASCII是電腦中最具支配地位的標準,因此這的確是一個很高的目標。
Unicode影響到了電腦工業的每一個部分,但也許會對做業系統和程序設計語言的影響最大。從這方面來看,咱們已經上路了。Windows NT從底層支持Unicode(不幸的是,Windows 98只是小部分支援Unicode)。先天即被ANSI束縛的C程序設計語言經過對寬字元集的支持來支持Unicode。
[編輯本段]爲何使用Unicode?
基本上,計算機只是處理數字。它們指定一個數字,來儲存字母或其餘字符。在創造Unicode以前,有數百種指定這些數字的編碼系統。沒有一個編碼能夠包含足夠的字符:例如,單單歐州共同體就[1][2]須要好幾種不一樣的編碼來包括全部的語言。即便是單一種語言,例如英語,也沒有哪個編碼能夠適用於全部的字母,標點符號,和經常使用的技術符號。這些編碼系統也會互相沖突。也就是說,兩種編碼可能使用相同的數字表明兩個不一樣的字符,或使用不一樣的數字表明相同的字符。任何一臺特定的計算機(特別是服務器)都須要支持許多不一樣的編碼,可是,不論何時數據經過不一樣的編碼或平臺之間,那些數據總會有損壞的危險。
GBK: 漢字國標擴展碼,基本上採用了原來GB2312-80全部的漢字及碼位,並涵蓋了原Unicode中全部的漢字20902,總共收錄了883個符號, 21003個漢字及提供了1894個造字碼位。 Microsoft簡體版中文Windows 95就是以GBK爲內碼,又因爲GBK同時也涵蓋了Unicode全部CJK漢字,因此也能夠和Unicode作一一對應。
GB碼,全稱是GB2312-80《信息交換用漢字編碼字符集 基本集》,1980年發佈,是中文信息處理的國家標準,在大陸及海外使用簡體中文的地區(如新加坡等)是強制使用的惟一中文編碼。P-Windows3.2和蘋果OS就是以GB2312爲基本漢字編碼, Windows 95/98則以GBK爲基本漢字編碼、但兼容支持GB2312。GB碼共收錄6763個簡體漢字、682個符號,其中漢字部分:一級字3755,以拼音排序,二級字3008,以偏旁排序。該標準的制定和應用爲規範、推進中文信息化進程起了很大做用。
GBK編碼是中國大陸制訂的、等同於UCS的新的中文編碼擴展國家標準。GBK工做小組於1995年10月,同年12月完成GBK規範。該編碼標準兼容GB2312,共收錄漢字21003個、符號883個,並提供1894個造字碼位,簡、繁體字融於一庫。
GBK碼對字庫中偏移量的計算公式爲:
[(GBKH-0xB0)*0x5E+(GBKL-0xA1)]*(漢字離散後每一個漢字點陣所佔用的字節)數據庫