互聯網開發常識譜--字符編碼

字符,字符集,字符編碼

什麼是字符

字符是一個信息單位,在計算機裏面,一箇中文漢字是一個字符,一個英文字母是一個字符,一個阿拉伯數字是一個字符,一個標點符號也是一個字符。

什麼是字符集

字符集是字符組成的集合,通常以二維表的形式存在,二維表的內容和大小是由使用者的語言而定,是英語,是漢語,還是阿拉伯語。字符集就規定了某個文字對應的二進制數字存放方式(編碼)和某串二進制數值代表了哪個文字(解碼)的轉換關係。

什麼是字符編碼

字符編碼是把字符集中的字符編碼爲特定的二進制數,以便在計算機中存儲。對於一個字符集來說要正確編碼轉碼一個字符需要三個關鍵元素:字庫表(character repertoire)、編碼字符集(coded character set)、字符編碼(character encoding form)。其中字庫表是一個相當於所有可讀或者可顯示字符的數據庫,字庫表決定了整個字符集能夠展現表示的所有字符的範圍。編碼方式一般就是對二維表的橫縱座標進行變換的算法。編碼字符集,即用一個編碼值code point來表示一個字符在字庫中的位置。字符編碼,將編碼字符集和實際存儲數值之間的轉換關係。一般來說都會直接將code point的值作爲編碼後的值直接存儲。例如在ASCII中A在表中排第65位,而編碼後A的數值是0100 0001也即十進制的65的二進制轉換結果。 一般都比較簡單,直接把橫縱座標拼一起就完事了。後來隨着字符集的不斷擴大,爲了節省存儲空間,纔出現了各種各樣的算法。

字符集和字符編碼一般都是成對出現的,如ASCII、IOS-8859-1、GB2312、GBK,都是即表示了字符集又表示了對應的字符編碼,以後統稱爲編碼。Unicode比較特殊,後面細說。

字符集的發展

單字節
美國製定了一套字符編碼,對英語字符與二進制位之間的關係,做了統一規定。這被稱爲ASCII碼(American Standard Code for Information Interchange),一直沿用至今。ASCII碼一共規定了128個字符的編碼,比如空格”SPACE”是32(二進制00100000),大寫的字母A是65(二進制01000001)。這128個符號(包括32個不能打印出來的控制符號),只佔用了一個字節的後面7位,最前面的1位統一規定爲0。

當計算機傳到了歐洲,國際標準化組織在ASCII的基礎上進行了擴展,形成了ISO-8859標準,兼容ASCII,在高128個碼位上有所區別。但是由於歐洲的語言環境十分複雜,所以根據各地區的語言又形成了很多子標準,ISO-8859-1、ISO-8859-2、ISO-8859-3、……、ISO-8859-16。

雙字節
單字節改雙字節,16位二進制數,65536個碼位。在不同國家和地區又出現了很多編碼,大陸的GB2312、港臺的BIG5、日本的Shift JIS等等。GBK是GB2312的擴展(K是拼音KuoZhan的縮寫)。

Unicode
Unicode,是一種所有符號的編碼,可以容納100多萬個符號。每個符號的編碼都不一樣,比如,U+0639表示阿拉伯字母Ain,U+0041表示英語的大寫字母A,U+4E25表示漢字”嚴”。漢字編碼範圍U+4E00-U+9FCB。正則表達式/[\u4e00-\u9fcb]+/。

字符編碼歷史

字符編碼 歷史
ASCII 1963
GB2312 1980
Unicode 1991
ISO-8859-1 1998
GBK 1993
UTF-8 1993
UTF-16 2000

UTF-8和Unicode的關係

Unicode是編碼字符集,而UTF-8就是字符編碼,即Unicode規則字庫的一種實現形式。Unicode的編號從0000開始一直到10FFFF共分爲16個Plane,每個Plane中有65536個字符。而UTF-8則只實現了第一個Plane,可見UTF-8雖然是一個當今接受度最廣的字符集編碼,但是它並沒有涵蓋整個Unicode的字庫,這也造成了它在某些場景下對於特殊字符的處理困難。
UTF-8編碼爲變長編碼。最小編碼單位(code unit)爲一個字節。一個字節的前1-3個bit爲描述性部分,後面爲實際序號部分。

Emoji

所謂Emoji就是一種在Unicode位於\u1F601-\u1F64F區段的字符。這個顯然超過了目前常用的UTF-8字符集的編碼範圍\u0000-\uFFFF。Emoji表情隨着IOS的普及和微信的支持越來越常見。一般來說MySQL數據庫的默認字符集都會配置成UTF-8(三字節),而utf8mb4在5.5以後才被支持,也很少會有DBA主動將系統默認字符集改成utf8mb4。那麼問題就來了,當我們把一個需要4字節UTF-8編碼才能表示的字符存入數據庫的時候就會報錯:ERROR 1366: Incorrect string value: ‘\xF0\x9D\x8C\x86’ for column 。 如果認真閱讀了上面的解釋,那麼這個報錯也就不難看懂了。我們試圖將一串Bytes插入到一列中,而這串Bytes的第一個字節是\xF0意味着這是一個四字節的UTF-8編碼。但是當MySQL表和列字符集配置爲UTF-8的時候是無法存儲這樣的字符的,所以報了錯。 那麼遇到這種情況我們如何解決呢?有兩種方式:升級MySQL到5.6或更高版本,並且將表字符集切換至utf8mb4。第二種方法就是在把內容存入到數據庫之前做一次過濾,將Emoji字符替換成一段特殊的文字編碼,然後再存入數據庫中。之後從數據庫獲取或者前端展示時再將這段特殊文字編碼轉換成Emoji顯示。

本文參考以下博文整理
字符,字符集,字符編碼
http://www.jianshu.com/p/bd7a6c508c33
十分鐘搞清字符集和字符編碼
http://cenalulu.github.io/linux/character-encoding/
漢字 Unicode 編碼範圍
http://www.qqxiuzi.cn/zh/hanzi-unicode-bianma.php

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