Unicode 與 UTF-8 的本質與轉換

對於大多數人來說,ASCII碼,Unicode,UTF-8等等,大家都耳熟了,但可能只是大概聽過但又沒有仔細深入瞭解。很多時候一旦遇到亂碼和編碼之類問題的時候就會蒙,無從下手。我最近也着手在寫些網絡相關的代碼,想更清楚瞭解內部的到底是什麼,故上網學習了下並作記錄

1.ASCII碼

計算機發展初期,美國需要用通過計算機來表達26個基本拉丁字母、阿拉伯數字和英式標點符號,通過制定編碼來表達它們。那既然是美國,那只需要表達英語和一些常的符號唄,反正不多,計劃用1個字節(即8個bit),一個bit表達0或1,從00000000到11111111,使用7位二進制表達,最高位用作奇偶校驗。
使用7位二進制數表達的內容是:

十進制範圍 十六進制範圍 表達的內容
0 ~ 31 (00000000 ~ 00011111) 控制字符
32 ~ 47 (00100000 ~ 00101111) 標點符號、運算符號
48 ~ 57 (01000001 ~ 00111001) 0到9十個阿拉伯數字
58 ~ 64 (00111010 ~ 01000000) 標點符號、運算符號
65 ~ 90 (00110000 ~ 01011010) 26個大寫英文字母
91 ~ 96 (01011011 ~ 01100000) 標點符號、運算符號
97 ~ 122 (01100001 ~ 01111010) 26個小寫英文字母
123~ 126 (01111011 ~ 01111110) 標點符號、運算符號
127 (01111111) 控制字符(DEL)

它們的排列是有規則的:

  1. 0-9<A-Z<a-z
  2. 同個字母的大寫字母比小寫字母要小32
  3. 同類型可比較字符呈現爲遞增,如0-9爲遞增的, A~Z爲遞增的

好了好了,其實這麼一說,好像本質的東西都講完了吧?就是每一個坑對應一個字符,用一個字節來表達就好了。

但是,隨着計算機要發展了,很多國家逐步普及使用,各個國家有各個國家的國歌,噢不是,是各個國家有各個國家的語言,明顯這一個字節是不夠的啊,例如我們中國漢字博大精深多達數萬個。

那麼問題來了,既然這麼多個國家,爲了大家有個可以大家都能唯一表達一個“字”的方法,那就全世界所有國家的字都定一個唯一碼,對應某個字,於是有個國際組織就搞了一套唯一碼,就是我們常見的Unicode,用一個獨一無二的編碼來表達一個字符。

2.Unicode

Unicode,它爲每種語言中的每個字符設定了統一併且唯一的二進制編碼,以滿足跨語言的要求,是一個字符集,charset。
既然是一個集合,對於計算機需要解析的時候,如果給出一串Unicode的時候,應該怎麼處理好呢?
我們假設一下:
如果按最長的字符來規定所有字符都是統一長度,這樣是可以解析出來,但是:漢字需要三個或四個字來達,類似像ASCII碼等只需要1個字節可以表達的,這樣子的話不就有兩個多餘的字節了嗎?
對於計算機科學家來說可是不樂意了,足足浪費了那麼多的字節。這個時候UTF-8就應運而生了。

3.UTF-8

既然有了唯一碼,又想節省字節來表達,意味着:有些長的,有些短的,就需要用變長來處理。
那麼,既然每個字節是變長的,那我要怎麼制定這個編碼規則呢?
UTF-8,它可以用1至4個字節對Unicode字符集中的所有有效編碼點進行編碼,屬於Unicode標準的一部分。
UTF-8 的編碼規則很簡單,只有2條:
1.對於單字節的符號,字節的第一位設爲0,後面7位爲這個符號的 Unicode 碼。
2.對於n字節的符號(n > 1),第一個字節的前n位都設爲1,第n + 1位設爲0,後面字節的前兩位全部設爲10。其餘標識爲“x”的二進制位,全部爲這個符號的Unicode碼,Unicode碼從右到左,按位置從右到左填入,不足的用0填充。

Unicode符號範圍(十進制) Unicode符號範圍(十六進制) Byte 1 Byte 2 Byte 3 Byte 4
0, 127 U+0000 - U+007F 0xxxxxxx
128, 2047 U+0080 - U+07FF 110xxxxx 10xxxxxx
2048, 65535 U+0800 - U+FFFF 1110xxxx 10xxxxxx 10xxxxxx
65536, 1114111 U+10000 - U+1FFFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

(爲了方便閱讀,多顯示一列10進制的範圍)

4.Unicode 與 UTF-8的轉換

既然有了字符集,又有編碼規則,那怎麼把一個Unicode轉換成UTF-8編碼呢?舉個例子,“樂”字。

  1. 先把“樂”字的Unicode碼找出來爲:4E50 (Unicode編碼表鏈接地址)
  2. 把“樂”的十六進制的Unicode轉換成二進制:‭0100111001010000‬
  3. 4E50處於編碼規則的第三行範圍內,故把第2步轉換的二進制填入,得:11100100 10111001 10010000‬
  4. 把填入規則後的二進制轉換成16進制:‭E4B990‬‬
  5. 最後得出“樂”字UTF-8編碼爲:‭E4B990‬
    如果想把UTF-8查看它的Unicode是什麼,把以上步驟反推即可。

5.小結;

對於字符集(charset)和編碼規則(UTF-8等)要有清晰的區分
Unicode是一個字符集,是把所有語言的每一個字符都給了一個唯一的“id”
UTF-8是編碼規則,如何通過變長規則把Unicode轉換成自己的編碼。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章