什么是字符集?
計(jì)算機(jī)發(fā)明出來后,科學(xué)家們遇到了一個(gè)問題,他們不知道該怎么將現(xiàn)實(shí)生活中的符號存儲進(jìn)計(jì)算機(jī)中。后來,他們想出了構(gòu)建一個(gè)字符集的方法,也就是給每一個(gè)符號都匹配一個(gè)二進(jìn)制數(shù)。
這樣存儲字符時(shí),就可以通過查閱字符集得到對應(yīng)的二進(jìn)制碼,將其存儲在存儲設(shè)備中。讀取數(shù)據(jù)時(shí),同樣是查閱字符集得到二進(jìn)制碼對應(yīng)的符號,然后將符號輸出。這樣一個(gè)字符集完美構(gòu)建了字符和二進(jìn)制之間的關(guān)系。
有圖有真相,展示下最常見的 ASCII 碼表吧。
ASCII 碼
這是美國人制定的一個(gè)只支持英文字母還有少許特殊字符的一個(gè)字符集。一共有 128 個(gè)字符,上圖已經(jīng)展示了對應(yīng)關(guān)系了。
ASCII 表中,每個(gè)字符只占一個(gè)字節(jié),且字節(jié)的第一位固定位 0 ,因?yàn)?7 位就能夠表示 128 個(gè)字符。如字母 A 對應(yīng)的二進(jìn)制形式是 01000001 。
非 ASCII 碼
對于非英語的國家,128 個(gè)字符無法表示他們的語言,這時(shí)候開始把前面閑置的一位也給用上了,倒是能解決一些問題。但還是不夠用,比如中文遠(yuǎn)遠(yuǎn)不止 256 個(gè)字符,這時(shí)候就要尋求更高端的字符集了。
然后各個(gè)語言都給自己配置了一套字符集,但這些字符集互相都不兼容,你不認(rèn)識我,我不認(rèn)識你。還是拿中文舉例,早先出現(xiàn)了 GB2312 碼,它在兼容了 ASCII 碼的情況下,加入了六千多個(gè)漢字,可是中文哪里只有這么點(diǎn)漢子呢?后來又出現(xiàn)了兼容 GB2312 的 GBK 編碼。所以,以后遇到 GB2312 和 GBK 碼就不用再迷糊了。
這時(shí)候 ISO 則發(fā)布了一款包含所有語言字符的一個(gè)字符集 unicode 。
Unicode 字符集
它給每一個(gè)字符都規(guī)定了對應(yīng)的二進(jìn)制數(shù),但是很多字符的二進(jìn)制碼位數(shù)是不同的,比如,漢字"嚴(yán)"的 unicode 是十六進(jìn)制數(shù) 4E25 ,這需要兩個(gè)字節(jié),而如字母 A 對應(yīng)的二進(jìn)制形式是 01000001 ,這只需要一個(gè)字節(jié)。
unicode 存在嚴(yán)重的兩個(gè)問題。第一,如果統(tǒng)一字符存儲的長度,勢必會造成很大的存儲資源浪費(fèi)。第二,在解碼時(shí),怎么判斷是一個(gè)字節(jié)表示一個(gè)符號,還是兩個(gè)字節(jié),甚至更多字節(jié)呢?
基于這樣的問題,所以 unicode 碼只給出了每個(gè)字符對應(yīng)的二進(jìn)制碼,并沒有規(guī)定應(yīng)該用多少個(gè)字節(jié)去存儲它。相當(dāng)與 Java 中的接口,制定了規(guī)范。
UTF-8 字符集
互聯(lián)網(wǎng)的普及,強(qiáng)烈要求出現(xiàn)一種統(tǒng)一的編碼方式。utf-8 應(yīng)運(yùn)而生,它就是 unicode 的其中之一的實(shí)現(xiàn)方式,相當(dāng)于 unicode 接口的實(shí)現(xiàn)類。
UTF-8最大的一個(gè)特點(diǎn),就是它是一種變長的編碼方式。它可以使用 1~4 個(gè)字節(jié)表示一個(gè)符號,根據(jù)不同的符號而變化字節(jié)長度。這樣就直接解決了統(tǒng)一長度造成的大量存儲資源浪費(fèi)的問題,按需分配嘛。
那它是如何解決讀的問題呢?解決方法如下
unicode 完全兼容 ASCII 碼,對于這部分字符,首字母為零,后七位為對應(yīng)的二進(jìn)制碼。如字母 A 對應(yīng)的二進(jìn)制形式是 01000001 。
對于需要占據(jù) n 字節(jié)的符號,它第一個(gè)字節(jié)的前 n 位規(guī)定為 1 ,第 n+1 位規(guī)定為 0 ,后面 n -1 個(gè)字節(jié)的前兩位一律規(guī)定為 10 。例如,“嚴(yán)” 的 unicode 是 4E25(100111000100101),根據(jù) utf-8 的實(shí)現(xiàn)方式, "嚴(yán)" 的 UTF-8 編碼需要三個(gè)字節(jié),即格式是 "1110xxxx 10xxxxxx 10xxxxxx " 。
然后,從字符對應(yīng)的最后一個(gè)二進(jìn)制位開始,依次從后向前填入格式中的 x,多出的位補(bǔ) 0 。所以,"嚴(yán)"的 UTF-8 編碼是 "11100100 10111000 10100101"。
讀取時(shí),自動忽略這些固定的描述信息后,再查看 unicode 規(guī)定的字符規(guī)范,就可以得到對應(yīng)字符了。
總結(jié)下就是,ASCII 只適用于英語,而實(shí)現(xiàn)了 unicode 編碼的 utf-8 適用于所有的語言符號,且兼容 ASCII 碼,所以以后所有涉及編碼的問題,都指定為 utf-8 哦。