Unicode 字符和UTF編碼的理解
Unicode 編碼的由來
我們都知道,計算機的內部全部是由二進制數字0, 1 組成的, 那麽計算機就沒有辦法保存我們的文字, 這怎麽行呢? 於是美國人就想了一個辦法(計算機是由美國人發明的),也把文字轉化成數字,計算機不就能夠保存文字了,所以美國人就制定了一張表,規定了文字與數字的一一對應,字符A 就對應數字65, 字符B 就對應數字66, 這張表就是著名的ASCII 碼表。由於美國人的文字比較少,就是a, b, c d 等等, 對應完了,發現一共使用了128個數字,這也太少了,一個字節都沒有使用了,所以就決定用一個字節來表示一個字符, 所以對於ASCII 碼來說,一個字符在計算機中就占用一個字節。碼表制定好了,生產計算機的時候直接把碼表內置到計算機中就可以了。
但是隨著計算機的推廣,它到達了歐洲,亞洲,這就有點問題了,因為計算機中只有英文,它不可能表達 和書寫其他國家的語言,比如漢語,日語等等, 這肯定也是不行的。於是各個國家的政府就制定各自的碼表, 好讓計算機也能表示本國的語言,就拿我國來說吧,GBK, GB2313 碼表就出現了。 這就會出現一個問題,相同的數字在不同的碼表中對應的文字可能不同, 這就有可能造成亂碼。國際友人發了一封電子郵件過來,打開一看亂碼了,各國之間的文件不能夠交換使用。這時國際標準化組織就想把各國的字符都統一起來,把它們放到一張碼表中,如果計算機中都內置這張表,那就不會出現亂碼了。和ASCII碼的想法一致,在這張表中,也是給每一個字符都分配一個獨一無二的數字。這張表就是Unicode碼表或Unicode編碼字符集,這每一個字符對應的數字稱之為做碼點(Code Point). 碼表的樣子如下
Unicode 字符集在計算機中的實現
Unicode 字符集的基礎非常簡單,就是給世界上的每一個文字都分配一個獨一無二的數字,這個數字稱之為碼點(code point), 比如 給字符A分配的數字是65, 給字符B 分配的數字是66,那麽 A的 碼點(code point)就是65, B 的code point 就是66. 但Unicode 相對於其他編碼又是非常復雜的,這主要是在於Unicode 字符在計算機中的實現上,這些數字怎麽在計算機中表示,用多少個字節?
由於當時提出制定Unicode字符集標準的時候,是在1990s 左右,那時各國的文字都比較少,都對應完了之後,發現並沒有超過6萬,正好在計算機中,兩個字節就可以表示6萬多個字(2^16 -1是65535),所以就決定用2個字節,16個bit 來表示Unicode 字符, 這就是最早的UCS-2編碼, 這16個bit 稱之為code uint(碼元), 這時 一個碼點就對應一個碼元。
但是隨著時間的推移,尤其是亞洲國家把大量的象形文字也加入到Unicode 編碼中,突然發現,65535的數量根本就裝不下這些文字,於是Unicode 編碼字符集也相應的進行了擴充,它把整個字符集分成了17個平面,每一個平面都能放2^16 個文字, 第一個平面就放置最初的UCS-2編碼中所定義的文字,叫做基本多文本平面Basic Multilingual Plane (or BMP), 所以基本多文本平面碼點的取值範圍是0x0000 - 0xFFFF, 其他的16個平面稱為補充平面(Supplementary Planes or Astral Planes), 它們的取值範圍從0x10000 開始 (0xFFFF + 1 就等於0x10000, 16進制的計算) 。 針對這種多平面的字符集,出現了不同的在計算機中的實現方式,那就是我們經常聽到的UTF-8, UTF-16, UTF-32.
UTF-16 就是對於在BMP 平面的文字用兩個字節(16個bit)進行表示,然後對於其他平面的文字用四個字節進行表示,四個字節表示稱之為surrogate pairs(代理對), 一對16 bit 來表示一個 字符。 由於一個16bit 稱之為碼元code unit, 一個字符對應的數字稱為碼點,這也就意味著,一個碼點要有2個碼元進行表示。
UTF-32 則是用32個bit, 4個字節來表示一個字符,所有的字符都占用4個字節, 這肯定沒有問題,但也造成了內存空間的浪費。
UTF-8則好一點,采用變長字節。
Unicode 字符和UTF編碼的理解