在本文的上篇中,大致介紹了一下字元集是個什麼東西,以及與漢字相關的幾個字元集的發展曆程,在接下來的這個部分裡,我計劃談一談上篇文末所提到的那兩個東西,一個是 UCS,一個是 UTF。
需要提前說明的是,有關 Unicode 的資訊在網上的散布很零散,有的資訊被廣泛傳播但是已經過時,甚至有的文中都沒有表明該文撰寫的時間點,比較權威的資訊源,例如 Wikipedia,對於某些詞條的解釋也是模糊不清甚至互相衝突的。因此,我這本部分中所寫的,將會是網路資訊與我自己個人知識的雜糅,而且出於題中的“閑談”二字,某些資訊的出處來源我也不會完全標明。
UCS,是 Universal Character Set 的首字母縮寫,還有一種說法是,它是 Unicode Character Set 的首字母縮寫。可奇怪的是,據說 Unicode 的正式名稱是 Universal multiple-octet coded character set,也可以寫作 UCS。到這裡,筆者已經差不多暈了,敬請方家指正。我個人傾向於前者,因為從各方面的資訊來看,UCS 都是一個和 ISO10646 關係緊密的術語,很少有人在 Unicode 相關的上下文中使用,即使有,也可能是一些寫作不是那麼嚴謹的文章的誤用。
UCS 有兩種,UCS-2 和 UCS-4。用兩個位元組來對 UCS 字元進行編碼的方案,稱之為 UCS-2,同理,用四個位元組對 UCS 字元進行編碼的方案,稱之為 UCS-4。UCS 的這兩種編碼都是定長的,也就是說,只要給定字元的個數,那麼用以編碼這些字元的位元組數量就已經確定,無非是乘以二還是四的區別。在 UCS 裡,只可能存在沒有被指定的代碼點(即對某個代碼點沒有賦予確定的字元),而不存在不能使用的代碼點。通過這些可以知道,UCS-2 最多隻能表示 65536 個字元。
在我的印象裡,最開始在 Windows 下接觸 Unicode 就是其號稱有 65536 個碼位,幾乎可以容納世界上所有語言的字元。這個認識一直深深地烙印在我的大腦裡,甚至在後來,明明知道光是漢字的個數就已經超過了 65536 而達到了 7 萬多,也沒有能導致我去質疑兩個位元組已經不夠對所有的 Unicode 字元進行編碼了。不過從我剛才找到的 Unicode 1.1 的相關資訊來看,代碼點只定義到了 U+FFFD,還沒有脫出 65536 的範圍,兩個位元組在當時的確是夠用的(從而可知,我的認知錯誤在於沒有能夠與時俱進,不清楚後來
Unicode 的發展)。
如果你只對某個字元在 Unicode 字元集中的代碼點有興趣,那顯然不需要考慮這個代碼點的數值究竟用多少個位元組來表示,可當你要落實到電腦程式上,要對之進行儲存或者傳輸時,那麼一個代碼點到底要佔用多大的空間就必須要確定下來了。正好比在 C 語言中,給你一個數字 1,你是計劃用一個 char 型的資料呢還是一個 short 的資料,或者是 int 甚至 long?在這個事情上,Unicode 規範中給出了三個官方的方案,分別是 UTF-8、UTF-16 和 UTF-32。UTF 這三個字母后面的數字是各個方案中最小編碼單元佔用的位元,除以
8 就是位元組數了。也就是說,如果是 UTF-8,編碼一個 Unicode 字元最少會用 1 個位元組,UTF-16 和 UTF-32 則分別是 2 個、4 個。請注意,說的是最少,還沒封頂呢。那麼最大呢?在本文中限於篇幅,不再給出各個方案的具體編碼規則,只說一下結論:UTF-8 編碼,目前對一個字元最長是 3 個位元組(當然也可能是 2 個),要是採用 UTF-16,則一個 Unicode 字元的編碼可能是 2 個位元組或者 4 個位元組(不可能是 3 個),要是 UTF-32,那是定死的,就是 4 個位元組。電腦基礎紮實的讀者在這兒應該馬上就產生一個疑惑,因為會想到超過一個位元組的資料在排列時一定會有位元組序的問題。這是沒錯的,也因此,UTF-16
有兩種形式,稱之為 UTF-16LE 和 UTF-16BE,分別對應小端位元組序和大端位元組序,UTF-32 同理。如果你對位元組序的問題有所困惑,請參閱拙文《位元組那些事兒》。對於絕大部分的兩個位元組可以表示的字元,UTF-16 和 UCS-2 的編碼是一樣的,這個絕大部分如果用數字來說,是 96.9%。但 UTF-16 的優勢在於,對於超出兩個位元組表示範圍的字元,它也有辦法來編碼,只是增加了編碼的長度而已,而
UCS-2 則就無能為力了。
一旦表示一個字元已經達到了要動用 4 個位元組的地步,和諧的面貌就開始出現了,UCS-4 和 UTF-32 成了一模一樣的東西,沒有任何差異,互為別名而已。ISO 組織和 Unicode 組織甚至在將來指定新的字元的代碼點上也達成了一致,以保證相互相容的長治久安局面。
最後順便要提一下,在曆史上還出現過一些其他的編碼方案,例如 UTF-1,UTF-7(甚至還有 UTF-9 和 UTF-18,不過千萬注意,這兩個是被作為愚人節笑話發出來的,別像國內一些媒體一樣上了這種當,當了真),這些東西,絕大部分已經不再鮮活了,除非有很大必要,是無需去做深入瞭解的,當然,如果誰喜歡把自己修鍊成電腦曆史學家,儘管去精研無妨。
在本文裡還有兩個和 UTF 有關的術語沒有解釋,一個是 BOM,全稱 Byte Order Mark,即位元組序標記,還有一個是 ZWNBSP,全稱 Zero Width Non Breaking Space,是為零寬度非換行空白。有興趣可以自行搜尋,它們引發的歧義並不多,而且失之於過於瑣細,所以不是本文的介紹對象。
對於 UCS 和 UTF 的大致介紹就到這裡了,這後一篇寫得不算多,卻費了很大的勁,因為斟酌哪些資訊要放進來,哪些要捨棄著實不容易。希望能夠達到我的小小初衷,能讓看到此文的朋友在短時間內瞭解到這些相關概念、術語的概貌。若果如此,幸甚至哉。
參考資料
1、http://www.elfdata.com/plugin/unicodefaqdata.html
2、http://www.cl.cam.ac.uk/~mgk25/unicode.html
3、http://en.wikipedia.org/wiki/UTF-8
4、http://en.wikipedia.org/wiki/UTF-16
5、http://en.wikipedia.org/wiki/UTF-32