對於大多數人來說,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) |
它們的排列是有規則的:
- 0-9<A-Z<a-z
- 同個字母的大寫字母比小寫字母要小32
- 同類型可比較字符呈現爲遞增,如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編碼呢?舉個例子,“樂”字。
- 先把“樂”字的Unicode碼找出來爲:4E50 (Unicode編碼表鏈接地址)
- 把“樂”的十六進制的Unicode轉換成二進制:0100111001010000
- 4E50處於編碼規則的第三行範圍內,故把第2步轉換的二進制填入,得:11100100 10111001 10010000
- 把填入規則後的二進制轉換成16進制:E4B990
- 最後得出“樂”字UTF-8編碼爲:E4B990
如果想把UTF-8查看它的Unicode是什麼,把以上步驟反推即可。
5.小結;
對於字符集(charset)和編碼規則(UTF-8等)要有清晰的區分
Unicode是一個字符集,是把所有語言的每一個字符都給了一個唯一的“id”
UTF-8是編碼規則,如何通過變長規則把Unicode轉換成自己的編碼。