寫代碼這麼久,忽然發現並不瞭解字符編碼。咱們天天寫下的代碼,或者文件,在計算機中到底是怎樣的存在?咱們都知道,計算機可以認識的只有 0
和 1
。因此,不論任何數據,最終在計算機中只是 0
和 1
的排列組合。那麼計算機時如何識別這些排列組合的呢?這就須要 字符編碼(Character encoding)
了。簡單的說,就是按照必定的規則將信息與其對應的 0
和 1
的排列組合對應起來,這樣計算機就能夠根據字符編碼識別出硬盤中的排列組合所表明的真實信息了。常見的 ASCII
UTF-8
GBK
等等,都是典型的字符編碼。計算機究竟是如何辨別這些字符編碼的,就要看一下具體的字符編碼原理。html
ASCII(American Standard Code for Information Interchange,美國信息交換標準代碼),是基於拉丁字母的一套電腦編碼系統。注意最後兩個字母是 II
,而不是羅馬數字 2。ASCII
是由美國國家標準協會制定的,標準的單字節字符編碼方案,用於基本文本的數據。起源於 50 年代後期,在 1967 年定案。它最初是美國國家標準,供不一樣計算機在相互通訊時用做共同遵照的西文字符編碼標準,它已被國際標準化組織定爲國際標準,稱爲 ISO 646 標準。適用於全部拉丁文字字母。segmentfault
標準 ASCII
碼使用單字符,即 8
個二進制位表示字符。第一位統必定爲 0
,實際使用後面 7
位來表示,因此 ASCII
碼一共規定了 128
個字符的編碼,包括全部的大小寫字母,數字 0 到 9,標點符號以及一些特殊控制字符。windows
標準 ASCII 碼錶以下:微信
ASCII
是美國標準,並不能知足其餘語言的需求。例如英鎊符號,中文漢字等等。西方一些國家使用 8
個二進制位來表示字符,最多能夠表示 256
個字符。顯然,對於漢字而言,一個字符不可能知足需求。ui
爲了擴充 ASCII
編碼,以用於顯示本國的語言,不一樣的國家和地區制定了不一樣的標準,由此產生了 GB2312
, BIG5
, JIS
等各自的編碼標準。這些使用 2
個字節來表明一個字符的各類漢字延伸編碼方式,稱爲 ANSI
編碼,又稱爲 MBCS(Muilti-Bytes Charecter Set,多字節字符集)
。在簡體中文系統下,ANSI 編碼表明 GB2312
編碼,在日文操做系統下,ANSI
編碼表明 JIS
編碼,因此在中文 windows下要轉碼成 gb2312
, gbk
只須要把文本保存爲 ANSI 編碼
便可。不一樣的 ANSI
編碼並不兼容,同一個二進制值在不一樣的編碼體系中可能表明不一樣的字,這就致使了 Unicode
的誕生。在介紹 Unicode
以前,簡單看一下 ANSI
中的中文編碼。編碼
GB2312
也是 ANSI
編碼裏的一種,對 ANSI
編碼最初始的 ASCII
編碼進行擴充,爲了知足國內在計算機中使用漢字的須要,中國國家標準總局發佈了一系列的漢字字符集國家標準編碼,統稱爲 GB碼
,或國標碼。其中最有影響的是於 1980 年發佈的《信息交換用漢字編碼字符集 基本集》,標準號爲 GB 2312-1980
,因其使用很是廣泛,也常被通稱爲國標碼。GB2312
編碼通行於我國內地;新加坡等地也採用此編碼。幾乎全部的中文系統和國際化的軟件都支持 GB 2312
。操作系統
GB2312
是一個簡體中文字符集,由 6763
個經常使用漢字和 682
個全角的非漢字字符組成。其中漢字根據使用的頻率分爲兩級。一級漢字 3755
個,二級漢字 3008
個。code
GB2312
的出現,基本知足了漢字的計算機處理須要,可是對於人名,古漢語等方面的罕用字,GB2312
不能處理,這就致使了 GBK
的出現。orm
GBK
採用雙字節表示,整體編碼範圍爲 8140-FEFE
,首字節在 81-FE
之間,尾字節在 40-FE
之間,剔除 xx7F
一條線。總計 23940
個碼位,共收入 21886
個漢字和圖形符號,其中漢字(包括部首和構件)21003
個,圖形符號 883
個。cdn
ANSI
編碼的缺點很明顯,同一個編碼值,在不一樣的編碼體系中表明着不一樣的字符,很容易形成亂碼。若是有一種編碼,將世界上全部的符號都融入其中,每一個符號都有對應的編碼值,這樣就不存在亂碼問題了。這就是 Unicode
編碼。
Unicode
編碼是一個很大的集合,如今的規模能夠容納 100 多萬個符號,每一個符號的編碼都不同。其實 Unicode
並非真正意義上的字符編碼,它只是一個字符集,規定了符號的二進制碼,卻沒有規定這個二進制碼應該如何存儲。Unicode
有一些具體的實現編碼,其中用途最普遍的莫屬 UTF-8
。
UTF-8
是使用最廣的 Unicode
的一種 Unicode 的實現方式 ,它是一種變長的編碼方式,使用 1 ~ 4 個字符表示一個符號,根據不一樣的符號而變化字符長度,提升了 Unicode 的編碼效率。先來看一下 UTF-8
對於不一樣字節數的符號的表示方法, x
表明可以使用的二進制位:
字節數 | 編碼規則 | 可表示字符數量 |
---|---|---|
1 字節 | 0xxxxxxx | 2的7次方 = 128 |
2 字節 | 11xxxxxx 10xxxxxx | 2的11次方 = 2048 |
3 字節 | 1110xxxx 10xxxxxx 10xxxxxx | 2的15次方 = 65536 |
4 字節 | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx | 2的21次方 = 4194304 |
由上面的表很容易發現 UTF-8
的編碼規則:
對於單字節符號,第一位爲 0
,後面 7
爲表示這個符號的 Unicode碼
。因此對於單字節符號,UTF-8
的表示方式與 ASCII
一致。
對於 n
字節的符號,第一個字節的前 n
位都爲 1
,第 n+1
位爲 0
,後面的全部字節前兩位均爲 10
,剩下的二進制位爲這個字符的 Unicode碼
。
使用這種變長編碼方式,對於單字節的符號僅需使用一個字節來表示,不會形成浪費。對於漢字來講,通常都是使用三個字符來表示。對於計算機來講,也很容易區分一個字符到底佔用幾個字節:
0
,這個字節就是一個字符1
,連續有多少個 1
,就表示當前字符佔用多少個字節除了 UTF-8
,相應的還有 UTF-16
。在 UTF-8
中,以 8
個二進制位表示一個字符,而在 UTF-16
中,以 16
個二進制位表示一個字符。16
個二進制位能夠直接表示 65536
個字符,因此在 UTF-16
中,漢字和英文字母具備一樣的地位,都是使用 16
個二進制位,即 2
個字節表示 1
個字符。對英文來講會形成浪費,可是對中文來講,能夠節省存儲空間。
關於字符編碼,應該有了一個大概的認識,在平常使用中,咱們要儘可能作到編碼的統一,避免出現亂碼的狀況。
參考文章:
文章同步更新於微信公衆號:
秉心說
, 專一 Java 、 Android 原創知識分享,LeetCode 題解,歡迎關注!