字符集
首先必須知道一個概念 - 字符集
計算機中的所有字符, 說到底都是用二進制的 0/1 排列組合來表示的, 因此就需要有一個規范來規定每個字符對應 0/1 排列組合, 這樣的規范就是字符集.
Unicode, ASCII, GB2312, GBK 都是字符集. UTF-8不是!
ASCII
最早的計算機在設計時采用 8 個 bit 作為一個字節 - byte, 所以, 一個字節能表示的范圍就是 00000000 到 11111111, 也就是 0 到 255, 一共 256 種狀態, 每一個狀態對應一個符號, 可以表示 256 個符號.
美國有關的標準化組織就出臺了 ASCII 編碼, 對英語字符, 數字以及部分符號與二進制位之間的關系, 做了統一規定, 一共規定了 128 個字符的編碼. 只占用了一個字節的后面 7 位, 最前面一位統一規定為 0, 一直沿用至今.
每個 ASCII 編碼占用一個字節, 即 8 bit.
如果加上最前面一位, 即后 128 個最前面一位為 1 的編碼, 被稱為擴展ASCII碼. 顯示英語用 前 128 個符號編碼就夠了, 但是用來表示其他語言是不夠的. 比如, 在法語中, 字母上方有注音符號, 它就無法用 ASCII 碼表示. 于是, 一些歐洲國家就利用字節中閑置的最高位編入新的符號. 比如, 法語中的 é 的編碼為 130(二進制10000010). 這樣一來, 這些歐洲國家使用的編碼體系, 可以表示最多 256 個符號.
但是中文怎么辦?
GBK與GB2312
如果要表示中文, 顯然一個字節是不夠的, 至少需要兩個字節, 而且還不能和 ASCII 編碼沖突, 所以, 中國制定了 GB2312 編碼, 用來把中文編進去.
后來發現這 GB2312 還是不夠用, 漢字實在是太多了, 于是國內程序員又對這個字符集進行了擴充, 總之最后擴充成了GBK標準, GBK 依舊使用兩個字節表示一個漢字. GBK 是在 GB2312 基礎上擴容后兼容 GB2312 的標準.
同理, 日文和韓文等其他語言也有這個問題. 為了統一所有文字的編碼, Unicode 應運而生.
Unicode
它為每種語言中的每個字符設定了統一并且唯一的二進制編碼, 能夠使計算機實現跨語言、跨平臺的文本轉換及處理.
Unicode 與 ASCII 是兼容的, 通常用兩個字節表示一個字符, 原有的英文編碼從單字節變成雙字節,只需要把高字節全部填為 0 就可以.
但是, 這里就有一個問題, 這些英文字母只需要一個字節就能存儲, 現在用兩個字節, 文件的體積就可能要擴大兩倍. 這沒辦法接受!
因此,Unicode 有了各種各樣的實現形式,最出名的是UTF-8
UTF-8
UTF-8 就是在互聯網上使用最廣的一種 Unicode 的實現方式.
UTF-8 最大的一個特點, 就是它是一種變長的編碼方式. 它可以使用1~4個字節表示一個符號, 根據不同的符號而變化字節長度.
UTF-8 的編碼規則:
- 對于單字節的符號, 字節的第一位設為0, 后面7位為這個符號的 Unicode 碼. 因此對于英語字母, UTF-8 編碼和 ASCII 碼是相同的.
- 對于 n 字節的符號(n > 1), 第一個字節的前 n 位都設為1, 第 n + 1 位設為 0, 后面字節的前兩位一律設為 10. 剩下的沒有提及的二進制位, 全部為這個符號的 Unicode 碼.
舉例:
Unicode符號范圍(十六進制) | UTF-8編碼方式(二進制) |
---|---|
0000 0000-0000 007F | 0xxxxxxx |
0000 0080-0000 07FF | 110xxxxx 10xxxxxx |
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx |
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
總結
- Unicode, ASCII, GB2312, GBK 都是字符集. UTF-8不是.
- Unicode 只規定了符號的二進制代碼, 并沒有規定這個二進制代碼應該如何進行存儲. UTF-8 是則是 Unicode 儲存的實現方式之一.
- GB2312 是為了解決 ASCII 不支持中文的問題.
- GBK 是在 GB2312 基礎上擴容后兼容 GB2312 的標準.