UTF8,Unicode 的區別(zt)

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-8、UTF-16、UTF-32都是將數字轉換到程序數據的編碼方案。
  Unicode字符集可以簡寫爲UCS(Unicode Character Set)。早期的Unicode標準有UCS-2、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、平面2、平面14、平面15、平面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、平面1、平面2和平面14上,它們對應着Unicode目前定義的99089個字符,其中包括71226個漢字。平面0、平面1、平面2和平面14上分別定義了52080、3419、43253和337個字符。平面2的43253個字符都是漢字。平面0上定義了27973個漢字。
  2.實現方式
  在Unicode中:漢字“字”對應的數字是23383。在Unicode中,我們有很多方式將數字23383表示成程序中的數據,包括:UTF-8、UTF-16、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-8、UTF-16、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-8、UTF-16、UTF-32、字節序和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)]*(漢字離散後每個漢字點陣所佔用的字節)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章