2012年4月13日 星期五

[轉貼]字元集

轉貼自 http://tw.group.knowledge.yahoo.com/m-c/listitem/view?iid=106
----------------------------------------------------------------------------
Multi-Byte Character

1990年代行銷全球的作業系統 Windows 必須面對混亂的問題。微軟的做法就是提供不同的內碼表(code page),到底一個碼要代表哪一個字符,就要看該環境採用哪一個內碼表。相信大家應該都有這樣的經驗:開啟了一份怪里怪氣的網頁、電子郵件,然後瘋狂的從十幾種內碼表當中猜測到底該用哪一個。

對於亞洲文字的內碼表,微軟使用了一種雙位元組字元集(DBCS, double-byte character set)。這種字元集並非完全都是雙位元,前128個碼和ASCII相同,只使用1個位元組;128以上的碼則根據某些規則決定是否要和下一個位元組合在一起當成一個字。總之就是某些字元使用1個位元組,某些字元使用2個位元組。微軟支援了四種DBCS的內碼表:正體中文(內碼表950,和Big5相容)、簡體中文(內碼表936,和GB2312相容)、日文(內碼表932)、韓文(內碼表940)

DBCS 每個字長度並不統一,對程式設計來說造成了一些困擾。例如想知道一個字串有幾個字,就不能單純計算字串的 byte 數,因為每個字佔用的位元組數不相同,唯一的方法就是直接去剖析字串。

由於仍然使用單個 byte 作為處理文字的基礎單位,所以像中文這種雙位元組的文字實際上是被肢解開來處理。舉例來說,假如有人的名字叫做「許功蓋」,那麼很多程式將無法正常的顯示出他的名字。

統一編碼

內碼表或許在僅使用單一語言的環境下運作良好,但只要在不同語言之間轉換資料許多問題就會浮現,除非知道一段文字使用哪一個內碼表,否則無法保證能正確顯示出來。同一個字碼在不同的內碼表往往代表著不同的字符,但一次只能使用一個內碼表,所以想在同一份文件裡顯示多國語言是非常困難的。

著手進行這個統一工作的組織有 ISO 和 Unicode,最後雙方互相合作,Unicode完全和ISO 10646所定義的通用字符集(Universal Character Set, UCS)相容。

雖然規劃中編碼量膨脹到十萬之譜,不過現實流通 Unicode 並未超過 65536 組,可以塞入16 bit 還有餘。Unicode將65536個碼分成許多區段,前128個碼就是 ASCII。其他語言則免不了有一番意識型態之爭,經過一番敲敲打打總算塞進去了。如0x0370到0x03FF是希臘字母,希伯來文使用0x0590到 0x05FF,中日韓表意符號(又被稱為CJK)使用0x3000到0x9FFF。

這裡要強調的一點是,Unicode只管規定「數值碼」和「符號」如何對應,這樣一個和字符對應的數值碼稱為Unicode Point,卻不管這個數值碼如何儲存、傳輸之類的問題。這點和以往不同,以前的字碼本身通常就是該字碼在記憶體裡面的模樣,例如「A」這個字母的碼是65(十六進制是0x41),我們通常就用一個byte裡面存放65,說這個代表「A」。但 Unicode則不然,例如中文的「象」這個字的 Unicode值是0x8C61,但是Unicode並沒有規定它在記憶體裡面的模樣必須是兩個 byte 存放0x8C61。

用 wide character 存放 UTF-16

最簡單的處理辦法就是直接規定2 byte作為一個字元基本單位,把數值碼放到兩個位元組裡面,例如「象」這個字的 Unicode Point 是0x8C61,我們就用2 byte 的寬字元存放0x8C61;而英文字母「X」的Unicode Point 是0x58,我們就用2 byte的空間存放0x0058。這種做法就是UTF-16或USC2,UTF即Unicode Transformation Format之縮寫。(注意UTF規劃的編碼量上超過16 bit,理論上wide char不夠用)

用 byte stream 存放 UTF-8

對於一輩子只寫程式給美國人的軟體從業人員來說,他們大概從來不會碰到256以上的字碼,甚至連128以上的字碼都很少用,使用16位元來儲存一個字顯然是一種浪費。所以有人就發明了一種處理Unicode的儲存格式叫做UTF-8,對於127以下的字元仍然用1個位元組來存放,於是對以往用習於使用ASCII的人來說完全不會感覺到任何差別,統一之前製作的文件都不必轉碼,碼照跑、舞照跳。

但是只要有人跨過了字碼128的雷池一步,他就得準備付出代價,從前的Big5一個字用2 byte,用了UTF-8就要 3 個 byte;泰文則從1 byte漲價到3 byte,意即以前的泰文文件轉成UTF-8體積會暴增三倍,導致資料庫體積暴增、網路傳輸速度劇減。UTF-8使用前置碼方式編碼,每個字長度從1 byte 到6 byte不等(但現在最多只用4個 byte),意味著計算字數之類的動作並不能簡單完成。

沒有留言:

張貼留言