主要內容
Unicode是由於傳統的字元編碼方式的局限性而產生的,例如ISO 8859所定義的字元雖然在不同的國家中廣泛地使用,可是在不同國家間卻經常出現不相容的情況。很多傳統的編碼方式都具有一個共通的問題,即其容許電腦進行雙語環境式的處理(通常使用拉丁字母以及其本地語言),但卻無法同時支援多語言環境式的處理(指可同時處理混合多種語言的情況)。
Unicode試圖將字位(字素,graphemes)與類字位字元加以認定與編碼,而非以不同的字形(glyphs)來加以區分。然而在漢字的個案來看,這樣方式有時會引起一字多形的認定爭議(詳見中日韓統一表意文字主題)。
在文字處理方面,Unicode的功用是為每一個字元提供一個唯一的代碼(即一組數字),而不是一種字形。換句話說,Unicode是將字元以一種抽象的方式來呈現,而將視覺上的演繹工作(例如字型大小、外觀形狀、字型形態、文體等)留給其他軟體來處理,例如網頁瀏覽器或是文字處理器。
為了使Unicode與已存在和廣泛使用的舊有編碼互相兼容,尤其是差不多所有電腦系統都支援的基本拉丁字母部分,所以Unicode的首256字元仍舊保留給ISO8859-1所定義的字元,使既有的西歐語系文字的轉換不需特別考量;另方面因相同的原因,Unicode 把大量相同的字元重複編到不同的字元碼中去,使得舊有紛雜的編碼方式得以和Unicode編碼間互相直接轉換,而不會遺失任何資訊 。舉例來說,全形格式區段包含了主要的拉丁字母的全形格式,在中文、日文、以及韓文字形當中,這些字元以全形的方式來呈現,而不以常見的半角形式顯示,這對豎排文字和等寬排列文字有重要作用。
起源
Unicode 是為了解決傳統的字元編碼方案的局限而產生的,例如ISO 8859所定義的字元雖然在不同的國家中廣泛地使用,可是在不同國家間卻經常出現不兼容的情況。很多傳統的編碼方式都有一個共同的問題,即容許電腦處理雙語環境(通常使用拉丁字母以及其本地語言),但卻無法同時支持多語言環境(指可同時處理多種語言混合的情況)。
幾乎所有電腦系統都支持基本拉丁字母,並各自支持不同的其他編碼方式。Unicode為了和它們相互兼容,其首256字元保留給ISO 8859-1所定義的字元,使既有的西歐語系文字的轉換不需特別考量;並且把大量相同的字元重複編到不同的字元碼中去,使得舊有紛雜的編碼方式得以和Unicode編碼間互相直接轉換,而不會丟失任何信息。舉例來說,全形格式區段包含了主要的拉丁字母的全形格式,在中文、日文、以及韓文字形當中,這些字元以全形的方式來呈現,而不以常見的半角形式顯示,這對豎排文字和等寬排列文字有重要作用。
在表示一個Unicode的字元時,通常會用“U+”然後緊接著一組十六進制的數字來表示這一個字元。在基本多文種平面(英文為 Basic Multilingual Plane,簡寫 BMP。它又簡稱為“零號平面”, plane 0)里的所有字元,要用四位十六進制數(例如U+4AE0,共支持六萬多個字元);在零號平面以外的字元則需要使用五位或六位十六進制數了。舊版的Unicode標準使用相近的標記方法,但卻有些微的差異:在Unicode 3.0里使用“U-”然後緊接著八位數,而“U+”則必須隨後緊接著四位數。
編碼類別
Unicode是國際組織制定的可以容納世界上所有文字和符號的字元編碼方案。目前的Unicode字元分為17組編排,0x0000 至 0xFFFF,每組稱為平面(Plane),而每平面擁有65536個碼位,共1114112個。然而目前只用了少數平面。UTF-8、UTF-16、UTF-32都是將數字轉換到程式數據的編碼方案。
通用字元集(Universal Character Set, UCS)是由ISO制定的ISO 10646(或稱ISO/IEC 10646)標準所定義的標準字元集。UCS-2用兩個位元組編碼,UCS-4用4個位元組編碼。
UCS-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。
平面0也有一個專用區:0xE000-0xF8FF,有6400個碼位。平面0的0xD800-0xDFFF,共2048個碼位,是一個被稱作代理區(Surrogate)的特殊區域。代理區的目的用兩個UTF-16字元表示BMP以外的字元。在介紹UTF-16編碼時會介紹。
如前所述在Unicode 5.0.0版本中,238605-65534*2-6400-2048=99089。餘下的99089個已定義碼位分布在平面0、平面1、平面2和平面14上,它們對應著Unicode定義的99089個字元,其中包括71226個漢字。平面0、平面1、平面2和平面14上分別定義了52080、3419、43253和337個字元。平面2的43253個字元都是漢字。平面0上定義了27973個漢字。
在Unicode中:漢字“字”對應的數字是23383(十進制),十六進制表示為5B57。在Unicode中,我們有很多方式將數字23383表示成程式中的數據,包括:UTF-8、UTF-16、UTF-32。UTF是“Unicode Transformation Format”的縮寫,可以翻譯成Unicode字元集轉換格式,即怎樣將Unicode定義的數字轉換成程式數據。
UTF-8
UTF-8以位元組為單位對Unicode進行編碼。從Unicode到UTF-8的編碼方式如下:
Unicode編碼(十六進制) | UTF-8 位元組流(二進制) |
000000-00007F | 0xxxxxxx |
000080-0007FF | 110xxxxx 10xxxxxx |
000800-00FFFF | 1110xxxx 10xxxxxx 10xxxxxx |
010000-10FFFF | 11110xxx10xxxxxx10xxxxxx10xxxxxx |
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-32
UTF-32編碼以32位無符號整數為單位。Unicode的UTF-32編碼就是其對應的32位無符號整數。UTF-32 (或 UCS-4)是一種將Unicode字元編碼的協定,對每一個Unicode碼位使用恰好32位元。其它的Unicode編碼則使用不定長度編碼。因為UTF-32對每個字元都使用4位元組,就空間而言,是非常沒有效率的。特別地,非基本多文種平面的字元在大部分檔案中通常很罕見,以致於它們通常被認為不存在占用空間大小的討論,使得UTF-32通常會是其它編碼的二到四倍。雖然每一個碼位使用固定長定的位元組看似方便,它並不如其它Unicode編碼使用得廣泛。
轉換方式
Unicode轉換為UTF-8
UTF-8的特點是對不同範圍的字元使用不同長度的編碼。對於0x00-0x7F之間的字元,UTF-8編碼與ASCII編碼完全相同。UTF-8編碼的最大長度是4個位元組。從表3-2可以看出,4位元組模板有21個x,即可以容納21位二進制數字。Unicode的最大碼位0x10FFFF也只有21位。
如:“漢”字的Unicode編碼是0x6C49。0x6C49在0x0800-0xFFFF之間,使用用3位元組模板了:1110xxxx 10xxxxxx 10xxxxxx。將0x6C49寫成二進制是:0110 1100 0100 1001, 用這個比特流依次代替模板中的x,得到:11100110 10110001 10001001,即E6 B1 89。
又如: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-8轉換為Unicode
將UTF-8轉換為Unicode的過程,實際上是將按UTF-8編碼規則填充至Unicode的編碼提取出來的過程,即將8位的位元組“xxxx xxxx”提取出來的過程,如某字元以“1110xxxx 10xxxxxx 10xxxxxx”的編碼方式進行UTF-8編碼,還原後UNICODE編碼為:“xxxx xxxx”。
例如字元“中”,二進制序列(雙位元組)為:0100 1110 0010 1101,進行UTF-8編碼後的位元組二進制序列(三位元組)為:1110 0100 10 111000 10 101101,進行UTF-8轉碼即去掉第一個位元組的“1110”,第二個位元組的“10”,第三個位元組的“10”,然後再將剩餘的二進制序列組合成一個雙位元組的二進制序列,即還原為:0100 1110 0010 1101,如此則完成轉碼。