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