Unicode碼
計算機科學領域的業界標準之一
統一碼,也叫萬國碼、單一碼(Unicode)是計算機科學領域裡的一項業界標準,包括字符集、編碼方案等。Unicode是為了解決傳統的字元編碼方案的局限而產生的,它為每種語言中的每個字元設定了統一併且唯一的二進位編碼,以滿足跨語言、跨平台進行文本轉換、處理的要求。1990年開始研發,1994年正式發布1.0版本,2020年發布13.0版本。
如果把各種文字編碼形容為各地的方言,那麼Unicode就是世界各國合作開發的一種語言。
在這種語言環境下,不會再有語言的編碼衝突,在同屏下,可以顯示任何語言的內容,這就是Unicode的最大好處。 就是將世界上所有的文字用2個位元組統一進行編碼。那樣,像這樣統一編碼,2個位元組就已經足夠容納世界上所有的語言的大部分文字了。
Unicode的學名是"Universal Multiple-Octet Coded Character Set",簡稱為UCS。
現在用的是UCS-2,即2個位元組編碼,而UCS-4是為了防止將來2個位元組不夠用才開發的。
Unicode(統一碼、萬國碼、單一碼)是一種在計算機上使用的字元編碼。1990年開始研發,1994年正式公布。隨著計算機工作能力的增強,Unicode也在面世以來的十多年裡得到普及。
Unicode是基於通用字符集(Universal Character Set)的標準來發展,並且同時也以書本的形式(The Unicode Standard,目前第五版由Addison-Wesley Professional出版,ISBN-10:0321480910)對外發表。
2005年3月31日推出的Unicode4.1.0。
2020年3月10日推出的Unicode13.0.0。
大概來說,Unicode編碼系統可分為編碼方式和實現方式兩個層次。
統一碼編碼方式
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)。group0的平面0被稱作BMP(Basic Multilingual Plane)。將UCS-4的BMP去掉前面的兩個零位元組就得到了UCS-2。
每個平面有2^16=65536個碼位。Unicode計劃使用了17個平面,一共有17*65536=1114112個碼位。在Unicode5.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編碼時會介紹。
如前所述在Unicode5.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個漢字。
統一碼實現方式
在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位元組流(二進位)
F ║0xxxxxxFF║110xxxxx 10xxxFFFF║1110xxxx 10xxxxxx 10xxx10FFFF║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,得到:1110 0110 1011 0001 0100 1001,即E6 B1 89。
例2:Unicode編碼0x20C30在0x010000-0x10FFFF之間,使用用4位元組模板了:11110xxx 10xxxxxx 10xxxxxx 10xxxxxx。將0x20C30寫成21位二進位數字(不足21位就在前面補0):0 0010 0000 1100 0011 0000,用這個比特流依次代替模板中的x,得到,即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,寫成二進位是:000011 0000。用前10位依次替代模板中的y,用后10位依次替代模板中的x,就得到:11011001 1101000,即0xD843 0xDC30。
按照上述規則,Unicode編碼0x10000-0x10FFFF的UTF-16編碼有兩個WORD,第一個WORD的高6位是110110,第二個WORD的高6位是110111。可見,第一個WORD的取值範圍(二進位)是到11111111,即0xD800-0xDBFF。第二個WORD的取值範圍(二進位)是到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。我們將這個範圍寫成二進位:110100-11
按照編碼的相反步驟,取出高低WORD的后10位,並拼在一起,得到
0 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之前,有數百種指定這些數字的編碼系統。沒有一個編碼可以包含足夠的字元:例如,單單歐洲共同體就[1][2]需要好幾種不同的編碼來包括所有的語言。即使是單一種語言,例如英語,也沒有哪一個編碼可以適用於所有的字母,標點符號,和常用的技術符號。這些編碼系統也會互相衝突。也就是說,兩種編碼可能使用相同的數字代表兩個不同的字元,或使用不同的數字代表相同的字元。任何一台特定的計算機(特別是伺服器)都需要支持許多不同的編碼,但是,不論什麼時候數據通過不同的編碼或平台之間,那些數據總會有損壞的危險。
大多數計算機採用ASCII碼(美國標準信息交換碼),它是表示所有大小寫字母、數字、標點符號和控制字元的7位編碼方案。統一碼(Unicode)包含ASCII碼,'\u0000'到'\u007F'對應全部128個ACSII字元。在JAVA中可以使用統一碼。
註:
3400-4DBF/4E00-9FFF/20000-3FFFF:CJK統一表意符號(CJK Unified Ideographs)
編碼範圍:說明
0000-007F:C0控制符及基本拉丁文(C0 Control and Basic Latin)
0080-00FF:C1控制符及拉丁文補充-1(C1 Control and Latin 1 Supplement)
0100-017F:拉丁文擴展-A(Latin Extended-A)
0180-024F:拉丁文擴展-B(Latin Extended-B)
0250-02AF:國際音標擴展(IPA Extensions)
02B0-02FF:空白修飾字母(Spacing Modifiers)
0300-036F:結合用讀音符號(Combining Diacritics Marks)
0370-03FF:希臘文及科普特文(Greek and Coptic)
0400-04FF:西里爾字母(Cyrillic)
0500-052F:西里爾字母補充(Cyrillic Supplement)
0530-058F:亞美尼亞語(Armenian)
0590-05FF:希伯來文(Hebrew)
0600-06FF:阿拉伯文(Arabic)
0700-074F:敘利亞文(Syriac)
0750-077F:阿拉伯文補充(Arabic Supplement)
0780-07BF:馬爾地夫語(Thaana)
07C0-077F:西非書面語言(N'Ko)
0800-085F:阿維斯塔語及巴列維語(Avestan and Pahlavi)
0860-087F:Mandaic
0880-08AF:撒馬利亞語(Samaritan)
0900-097F:天城文書(Devanagari)
0980-09FF:孟加拉語(Bengali)
0A00-0A7F:錫克教文(Gurmukhi)
0A80-0AFF:古吉拉特文(Gujarati)
0B00-0B7F:奧里亞文(Oriya)
0B80-0BFF:泰米爾文(Tamil)
0C00-0C7F:泰盧固文(Telugu)
0C80-0CFF:卡納達文(Kannada)
0D00-0D7F:德拉維族語(Malayalam)
0D80-0DFF:僧伽羅語(Sinhala)
0E00-0E7F:泰文(Thai)
0E80-0EFF:寮國文(Lao)
0F00-0FFF:藏文(Tibetan)
1000-109F:緬甸語(Myanmar)
10A0-10FF:喬治亞語(Georgian)
1100-11FF:朝鮮文(Hangul Jamo)
1200-137F:衣索比亞語(Ethiopic)
1380-139F:衣索比亞語補充(Ethiopic Supplement)
13A0-13FF:切羅基語(Cherokee)
1400-167F:統一加拿大土著語音節(Unified Canadian Aboriginal Syllabics)
1680-169F:歐甘字母(Ogham)
16A0-16FF:如尼文(Runic)
1700-171F:塔加拉語(Tagalog)
1720-173F:Hanunóo
1740-175F:Buhid
1760-177F:Tagbanwa
1780-17FF:高棉語(Khmer)
1800-18AF:蒙古文(Mongolian)
18B0-18FF:Cham
1900-194F:Limbu
1950-197F:德宏泰語(Tai Le)
1980-19DF:新傣仂語(New Tai Lue)
19E0-19FF:高棉語記號(Kmer Symbols)
1A00-1A1F:Buginese
1A20-1A5F:Batak
1A80-1AEF:Lanna
1B00-1B7F:巴厘語(Balinese)
1B80-1BB0:巽他語(Sundanese)
1BC0-1BFF:Pahawh Hmong
1C00-1C4F:雷布查語(Lepcha)
1C50-1C7F:Ol Chiki
1C80-1CDF:曼尼普爾語(Meithei/Manipuri)
1D00-1D7F:語音學擴展(Phonetic Extensions)
1D80-1DBF:語音學擴展補充(Phonetic Extensions Supplement)
1DC0-1DFF:結合用讀音符號補充(Combining Diacritics Marks Supplement)
1E00-1EFF:拉丁文擴充附加(Latin Extended Additional)
1F00-1FFF:希臘語擴充(Greek Extended)
2000-206F:常用標點(General Punctuation)
2070-209F:上標及下標(Superscripts and Subscripts)
20A0-20CF:貨幣符號(Currency Symbols)
20D0-20FF:組合用記號(Combining Diacritics Marks for Symbols)
2100-214F:字母式符號(Letterlike Symbols)
2150-218F:數字形式(Number Form)
2190-21FF:箭頭(Arrows)
2200-22FF:數學運算符(Mathematical Operator)
2300-23FF:雜項工業符號(Miscellaneous Technical)
2400-243F:控制圖片(Control Pictures)
2440-245F:光學識別符(Optical Character Recognition)
2460-24FF:封閉式字母數字(Enclosed Alphanumerics)
2500-257F:製表符(Box Drawing)
2580-259F:方塊元素(Block Element)
25A0-25FF:幾何圖形(Geometric Shapes)
2600-26FF:雜項符號(Miscellaneous Symbols)
2700-27BF:印刷符號(Dingbats)
27C0-27EF:雜項數學符號-A(Miscellaneous Mathematical Symbols-A)
27F0-27FF:追加箭頭-A(Supplemental Arrows-A)
2800-28FF:盲文點字模型(Braille Patterns)
2900-297F:追加箭頭-B(Supplemental Arrows-B)
2980-29FF:雜項數學符號-B(Miscellaneous Mathematical Symbols-B)
2A00-2AFF:追加數學運算符(Supplemental Mathematical Operator)
2B00-2BFF:雜項符號和箭頭(Miscellaneous Symbols and Arrows)
2C00-2C5F:格拉哥里字母(Glagolitic)
2C60-2C7F:拉丁文擴展-C(Latin Extended-C)
2C80-2CFF:古埃及語(Coptic)
2D00-2D2F:喬治亞語補充(Georgian Supplement)
2D30-2D7F:提非納文(Tifinagh)
2D80-2DDF:衣索比亞語擴展(Ethiopic Extended)
2E00-2E7F:追加標點(Supplemental Punctuation)
2E80-2EFF:CJK部首補充(CJK Radicals Supplement)
2F00-2FDF:康熙字典部首(Kangxi Radicals)
2FF0-2FFF:表意文字描述符(Ideographic Description Characters)
3000-303F:CJK符號和標點(CJK Symbols and Punctuation)
3040-309F:日文平假名(Hiragana)
30A0-30FF:日文片假名(Katakana)
3100-312F:注音字母(Bopomofo)
3130-318F:朝鮮文兼容字母(Hangul Compatibility Jamo)
3190-319F:象形字註釋標誌(Kanbun)
31A0-31BF:注音字母擴展(Bopomofo Extended)
31C0-31EF:CJK筆畫(CJK Strokes)
31F0-31FF:日文片假名語音擴展(Katakana Phonetic Extensions)
3200-32FF:封閉式CJK文字和月份(Enclosed CJK Letters and Months)
3300-33FF:CJK兼容(CJK Compatibility)
3400-4DBF:CJK統一表意符號擴展A(CJK Unified Ideographs Extension A)
4DC0-4DFF:易經六十四卦符號(Yijing Hexagrams Symbols)
4E00-9FFF:CJK統一表意符號(CJK Unified Ideographs)
A000-A48F:彝文音節(Yi Syllables)
A490-A4CF:彝文字根(Yi Radicals)
A500-A61F:Vai
A660-A6FF:統一加拿大土著語音節補充(Unified Canadian Aboriginal Syllabics Supplement)
A700-A71F:聲調修飾字母(Modifier Tone Letters)
A720-A7FF:拉丁文擴展-D(Latin Extended-D)
A800-A82F:Syloti Nagri
A840-A87F:八思巴字(Phags-pa)
A880-A8DF:Saurashtra
A900-A97F:爪哇語(Javanese)
A980-A9DF:Chakma
AA00-AA3F:Varang Kshiti
AA40-AA6F:Sorang Sompeng
AA80-AADF:Newari
AB00-AB5F:越南傣語(Vi?t Thái)
AB80-ABA0:Kayah Li
AC00-D7AF:朝鮮文音節(Hangul Syllables)
D800-DBFF:High-half zone of UTF-16
DC00-DFFF:Low-half zone of UTF-16
E000-F8FF:自行使用區域(Private Use Zone)
F900-FAFF:CJK兼容象形文字(CJK Compatibility Ideographs)
FB00-FB4F:字母表達形式(Alphabetic Presentation Form)
FB50-FDFF:阿拉伯表達形式A(Arabic Presentation Form-A)
FE00-FE0F:變數選擇符(Variation Selector)
FE10-FE1F:豎排形式(Vertical Forms)
FE20-FE2F:組合用半符號(Combining Half Marks)
FE30-FE4F:CJK兼容形式(CJK Compatibility Forms)
FE50-FE6F:小型變體形式(Small Form Variants)
FE70-FEFF:阿拉伯表達形式B(Arabic Presentation Form-B)
FF00-FFEF:半型及全型形式(Halfwidth and Fullwidth Form)
FFF0-FFFF:特殊(Specials)
10000–1FFFF:第1輔助平面,多文種補充平面(Supplementary Multilingual Plane,SMP)
20000–2FFFF:第2輔助平面,表意文字補充平面(Supplementary Ideographic Plane,SIP)
40000–DFFFF:第4-13輔助平面,尚未使用
E0000–EFFFF:第14輔助平面,特別用途補充平面(Supplementary Special-purpose Plane,SSP)
F0000–FFFFF:第15輔助平面,保留作為私人使用區(Private Use Area,PUA)
100000–10FFFF:第16輔助平面,保留作為私人使用區(Private Use Area,PUA)