詳解Unicode字符集以及字符編碼實(shí)現(xiàn)(一)
在日常生活中,我們經(jīng)常會(huì)碰到打開(kāi)一個(gè)文件,但是文件內(nèi)容亂碼的問(wèn)題,比如我想看《西游記》這部小說(shuō)。
下載鏈接:https://m.ijjjxs.com/txt/dl-35-12585.html
點(diǎn)擊TXT電子書(shū)下載,很快就會(huì)下載完成,但是使用電腦自帶的TXT工具打開(kāi)發(fā)現(xiàn)亂碼,這個(gè)時(shí)候你是不是有種被騙的感覺(jué)?

其實(shí)網(wǎng)站并沒(méi)有騙你,只是沒(méi)有弄清楚字符編碼的問(wèn)題,那么什么是字符編碼,如何盡量避免這種情況出現(xiàn),接下來(lái)本文將詳細(xì)討論所有的細(xì)節(jié),并使用代碼實(shí)現(xiàn)Unicode字符集在計(jì)算機(jī)中的顯示。
內(nèi)容亂碼的問(wèn)題你可以選擇帶有多個(gè)字符編碼的編輯器打開(kāi),具體到《西游記》這部小說(shuō)中,
當(dāng)我選擇CLion打開(kāi)文件之后,提示我"The file was loaded in a wrong encoding: 'UTF-8'",

當(dāng)更換它的編碼格式為GB2312時(shí),文件內(nèi)容能夠正常顯示,什么是GB2312,這中間計(jì)算機(jī)做了什么?
(一)計(jì)算機(jī)基礎(chǔ)知識(shí)
二進(jìn)制
1854年,英國(guó)數(shù)學(xué)家喬治·布爾發(fā)表了一篇里程碑式的論文,其中詳細(xì)介紹了一種代數(shù)化的邏輯系統(tǒng),后人稱之為布爾代數(shù)。他提出的邏輯演算在后來(lái)的電子電路設(shè)計(jì)中起基礎(chǔ)性作用。
1937年,克勞德·香農(nóng)在麻省理工大學(xué)完成了其電氣工程碩士學(xué)位論文《繼電器與開(kāi)關(guān)電路的符號(hào)分析》,用繼電器和開(kāi)關(guān)實(shí)現(xiàn)了布爾代數(shù)和二進(jìn)制算術(shù)運(yùn)算,其中香農(nóng)的理論奠定了數(shù)字電路的理論基礎(chǔ)。
二進(jìn)制中每個(gè)數(shù)字稱為一個(gè)比特(Bit,Binary digit 的縮寫(xiě))。
加法:0+0=0,0+1=1,1+0=1,1+1=10
減法:0-0=0,1-0=1,1-1=0,10-1=1
乘法:0×0=0,0×1=0,1×0=0,1×1=1
除法:0÷1=0,1÷1=1
字節(jié)
通常以8個(gè)比特作為一個(gè)字節(jié)(Byte),日常生活中的計(jì)量單位:
1 Byte = 8 Bit
1KB = 1024 Byte
1MB =?1024?KB
1GB?= 1024 MB
(二)ASCII編碼
維基百科:字符編碼
https://zh.wikipedia.org/zh-cn/%E5%AD%97%E7%AC%A6%E7%BC%96%E7%A0%81
令人尷尬的是當(dāng)我想把維基百科關(guān)于字符編碼的網(wǎng)址粘貼上來(lái)時(shí),發(fā)現(xiàn)又出現(xiàn)亂碼,這雖然不影響使用,但是極大地影響文章的美觀性,它為什么不能顯示成這樣?
https://zh.wikipedia.org/zh-cn/字符編碼
當(dāng)我將帶有中文的這個(gè)網(wǎng)址粘貼到瀏覽器上去,發(fā)現(xiàn)它竟然還是能訪問(wèn)到對(duì)應(yīng)的網(wǎng)頁(yè),真是太讓人匪夷所思?
查看“字”的字符編碼
https://www.compart.com/en/unicode/U+5B57
UTF-8 Encoding: 0xE5 0xAD 0x97
神奇地發(fā)現(xiàn)這里的0xE5 0xAD 0x97和前面的網(wǎng)址%E5%AD%97是一一對(duì)應(yīng)的,現(xiàn)在是迫切地需要知道什么是字符編碼,才能解釋剛剛所發(fā)生的事情。
在19世紀(jì)電報(bào)的發(fā)展徹底改變了信息的遠(yuǎn)距離傳輸方式之前,中國(guó)、埃及和希臘等古代文明使用鼓聲、信號(hào)火或煙霧信號(hào)在遙遠(yuǎn)的點(diǎn)之間交換信息。
美國(guó)發(fā)明家薩繆爾·摩爾斯在1837年發(fā)明了電報(bào),還發(fā)展出一套將字母及數(shù)字編碼以便拍發(fā)的方法,稱為摩斯電碼。

這應(yīng)該是現(xiàn)代計(jì)算機(jī)字符編碼的雛型,使用點(diǎn)和線表示26個(gè)英文字母以及10個(gè)數(shù)字。
ASCII(American?Standard?Code for?Information?Interchange,美國(guó)信息交換標(biāo)準(zhǔn)代碼)是基于拉丁字母的一套電腦編碼系統(tǒng)。第一版標(biāo)準(zhǔn)發(fā)布于1963年,最后一次更新則是在1986年,至今為止共定義了128個(gè)字元。
控制字符的編號(hào)范圍是0 - 31和127,共33個(gè)字符。
可顯示字符的編號(hào)范圍是32 - 126,共95個(gè)字符,其中48 - 57為0到9十個(gè)阿拉伯?dāng)?shù)字,65 - 90為26個(gè)大寫(xiě)英文字母,97 - 122為26個(gè)小寫(xiě)英文字母,其余為一些標(biāo)點(diǎn)符號(hào)、運(yùn)算符號(hào)等。

根據(jù)以上定義,可以將字符編碼轉(zhuǎn)換為二進(jìn)制編碼,使用Byte作為基礎(chǔ)單位。
比如大寫(xiě)的字母A,它的十進(jìn)制編碼為65,它的二進(jìn)制編碼為
01000001 = 01000000 (十進(jìn)制64) + 00000001 (十進(jìn)制1)
如果要表示Hello這個(gè)單詞,可以對(duì)應(yīng)地查找字符表進(jìn)行轉(zhuǎn)換:
01001000 01100101 01101100 01101100 01101111
(三)Unicode編碼
ASCII碼非常簡(jiǎn)潔,完美地處理了美國(guó)的字符編碼,但是它有個(gè)致命的缺陷,很多其它國(guó)家的字符它沒(méi)有辦法處理,比如日文的你好(こんにちは)。
此時(shí)很多國(guó)家各顯神通。
中國(guó)發(fā)明GB/T?2312,全稱《信息交換用漢字編碼字符集·基本集》,標(biāo)準(zhǔn)共收錄6763個(gè)漢字,其中一級(jí)漢字3755個(gè),二級(jí)漢字3008個(gè);同時(shí)收錄了包括拉丁字母、希臘字母、日文平假名及片假名字母、俄語(yǔ)西里爾字母在內(nèi)的682個(gè)字符。
韓國(guó)發(fā)明KS X 1001,包含諺文2350字、漢字4888字、英文字母、數(shù)字和假名共8226字。
在GB/T 2312中每個(gè)漢字及符號(hào)的碼位使用兩個(gè)字節(jié)來(lái)表示,這樣看上去也很簡(jiǎn)潔,只是比ASCII多一個(gè)字節(jié)的使用。
但是它存在很大的問(wèn)題,比如想要輸入緬甸語(yǔ)?????????(你好),沒(méi)有辦法輸入字符集中不存在的字符,它沒(méi)法滿足不同文化之間的交流。
就在此時(shí)Unicode橫空出世,Unicode全稱為Unicode標(biāo)準(zhǔn)(The Unicode Standard),其整理、編碼了世界上大部分的文字系統(tǒng),使得電腦能以通用劃一的字符集來(lái)處理和顯示文字,不但減輕在不同編碼系統(tǒng)間切換和轉(zhuǎn)換的困擾,更提供了一種跨平臺(tái)的亂碼問(wèn)題解決方案。
Unicode廣泛應(yīng)用于電腦軟件的國(guó)際化與本地化過(guò)程。
Unicode編碼非常暴力,?在它的標(biāo)準(zhǔn)中
http://www.unicode.org/versions/Unicode8.0.0/appC.pdf
它定義了UCS-4 stands for “Universal Character Set coded in 4 octets.”去表示每個(gè)字符,也就是說(shuō)它最大可以表示2^32次方 =?4294967296個(gè)字符。

可以看到“人”使用U+4EBA這個(gè)十六進(jìn)制數(shù)表示,“雨傘”使用U+2602表示,用U+的方式表示所有它能夠表示的字符。
到這里好像事情進(jìn)入大結(jié)局,有個(gè)統(tǒng)一字符集,如果都采用它那就不會(huì)出現(xiàn)亂碼問(wèn)題呀?其實(shí)以上并沒(méi)有講述計(jì)算機(jī)是怎么表示它們的。接下來(lái)就會(huì)帶你看到UTF8/UTF16/UTF32閃亮登臺(tái),一個(gè)驅(qū)魔亂舞的時(shí)代!