各位:請(qǐng)自帶飲料自帶茶,自帶板凳自帶糖,坐好,憋說(shuō)話,我講個(gè)故事,你仔細(xì)聽(tīng),講完留作業(yè)!
很久以前,有一群美國(guó)人,他們發(fā)明了計(jì)算機(jī)之后,想用一個(gè)字節(jié)也就是八位二進(jìn)制數(shù)來(lái)表示一切可以形象化的文字。比如我想保存字母a
,我就把01100001
傳給計(jì)算機(jī)幫我保存起來(lái),這個(gè)過(guò)程叫編碼(encode);反之,當(dāng)計(jì)算機(jī)讀取數(shù)據(jù)遇到01100001
時(shí),計(jì)算機(jī)就顯示字母a
,這個(gè)過(guò)程呢,叫做解碼(decode)。后來(lái)這群人無(wú)恥的制定了一套標(biāo)準(zhǔn),試圖統(tǒng)治世界,這就是ASCII碼。他們掰著手指加上能想到的控制符號(hào),也就編到了127號(hào),這群美國(guó)佬發(fā)現(xiàn)自己真是太牛逼了,他們天真的認(rèn)為我們把128 - 255的編碼位置留出來(lái),我能encode一個(gè)宇宙。
后來(lái),歐洲人也用計(jì)算機(jī)了,歐洲人發(fā)現(xiàn)美國(guó)佬真的是仗義,還給他們留著一半的編碼空間,于是貪婪的歐洲佬把128-255的編碼位置全都占了,這也就是我們常說(shuō)的不是國(guó)際標(biāo)準(zhǔn)的擴(kuò)展ASCII碼表的其中一種。
再后來(lái),計(jì)算機(jī)傳到了我們偉大的祖國(guó),當(dāng)時(shí)的計(jì)算機(jī)專家掐指一算,大約最起碼我們要6000多個(gè)編碼位置就夠啦,勤勞聰慧的中國(guó)人民就可以用上可以顯示漢字的電腦啦,后來(lái)看了ASCII碼表之后有一位專家提出,哎呀,256個(gè),不如還是我們一起去學(xué)英語(yǔ)呀。后來(lái)這名專家被打了一頓之后,去了教育局。
其他的專家一看,我擦,有些字符集127號(hào)之后都是啥鬼畫(huà)符,于是,我們偉大的前輩毫不猶豫的拋棄了那群貪婪的人添加的字符集擴(kuò)展部分,并大膽提出:127號(hào)之前的兼容ACSII碼表,我們把大于127的兩個(gè)字節(jié)連在一起,表示一個(gè)漢字,第一個(gè)字節(jié)為高位字節(jié)
(也叫區(qū)字節(jié)
),第二個(gè)字節(jié)為低位字節(jié)
(也叫位字節(jié)
),高位字節(jié)
使用了0xA1-0xF7
,低位字節(jié)
使用了0xA1-0xFE
。這樣我們大約搞出了6763個(gè)漢字以及非漢字圖形符號(hào)682個(gè),并且我們把ACSII本身存在的標(biāo)點(diǎn)·數(shù)字·字母
重新以兩個(gè)字節(jié)的編碼方式重新搞了一個(gè)放到里面,這就是我們常說(shuō)的全角字符
,原ACSII127號(hào)以下的也就是我們說(shuō)的半角字符
啦。前輩們給它起了一個(gè)名字:信息交換用漢字編碼字符集
,也就是我們常說(shuō)的GB2312
。
好景不長(zhǎng),五千年的風(fēng)和雨啊,不是鬧著玩的,你爸去給你落戶的時(shí)候發(fā)現(xiàn)計(jì)算機(jī)打不出這個(gè)字。面對(duì)這種情況,我們干脆不再要求位字節(jié)要大于127,只要區(qū)字節(jié)大于127就可以。它兼容GB2312,同時(shí)收錄內(nèi)容也提升至23940個(gè)碼位,其中有漢字21003這也就是漢字內(nèi)碼擴(kuò)展規(guī)范
,也就是我們常說(shuō)的GBK
。
經(jīng)過(guò)上面過(guò)程的演變,我國(guó)的人民終于可以更方便的使用計(jì)算機(jī)了。老一輩程序員也非常高興,就這樣,這種雙字節(jié)字符集在坊間廣泛流傳了起來(lái),相信一定聽(tīng)過(guò)一句名言:一個(gè)漢字是兩個(gè)英文字符
。
就這樣,在我們沾沾自喜的時(shí)候,世界各地計(jì)算機(jī)開(kāi)發(fā)者以及使用者也如雨后春筍,字符集以及編碼規(guī)范也是百家爭(zhēng)鳴,互不兼容,亂碼遍地,就在大家苦惱不已但又誰(shuí)都不服誰(shuí)的時(shí)候,有兩撥人不僅意識(shí)到這個(gè)問(wèn)題的嚴(yán)重性,而且著手創(chuàng)建一個(gè)通用字符集,其中一撥人就是國(guó)際標(biāo)準(zhǔn)化組織
(ISO
),他們制定了UCS
字符集(Universal Character Set
),另一撥人則是美國(guó)多語(yǔ)言服務(wù)提供商的財(cái)團(tuán)發(fā)起的Unicode
項(xiàng)目,他們都用四位十六進(jìn)制數(shù),也就是兩個(gè)字節(jié)來(lái)表示一個(gè)字符,也就是65535個(gè)碼位(后續(xù)有UCS-4
,也就是四個(gè)字節(jié)表示一個(gè)字符,共21億個(gè)字符,應(yīng)該夠用了哦)。后來(lái),兩撥人意識(shí)到世界上不需要兩個(gè)統(tǒng)一的通用字符集,所以他們合作制定了一個(gè)字符表,也就是我們目前所見(jiàn)最多,打破你一個(gè)漢字是兩個(gè)英文字符的觀點(diǎn)的Unicode/UCS
(多少次老師殷切的叮嚀變成你被其他程序員恥笑的理由)。
在這里要說(shuō)一下,Unicode/UCS
只是字符集,每一個(gè)字符雖然對(duì)應(yīng)一個(gè)碼位,但是用什么字節(jié)以及多少個(gè)字節(jié)來(lái)表示這個(gè)字符,是由字符編碼決定的,上面我們提到的ASCII
,GB2312
,GBK
等地區(qū)編碼標(biāo)準(zhǔn)制定時(shí),一般字符集和字符編碼時(shí)同時(shí)制定的,也就是說(shuō)ASCII
等不僅僅是字符集,更是一種字符編碼格式。
Unicode只是一個(gè)字符集,它的字符編碼有UTF-8,UTF-16,UTF-32。隨著計(jì)算機(jī)網(wǎng)絡(luò)的興起,UTF-8編碼越來(lái)越體現(xiàn)出他的優(yōu)勢(shì):不僅可以向前兼容ASCII碼,是變長(zhǎng)的編碼,并且由于編碼沒(méi)有狀態(tài),所以很容易重新同步,在傳輸過(guò)程中丟失了一些字節(jié)后,具有魯棒性。
我們來(lái)看一下UTF-8對(duì)Unicode進(jìn)行編碼的方式如下:
比如,“漢”字的Unicode編碼是U+6C49。0x6C49在0x0800-0xFFFF之間,使用用3字節(jié)模板了:1110xxxx 10xxxxxx 10xxxxxx。將0x6C49寫(xiě)成二進(jìn)制是:0110 1100 0100 1001, 用這個(gè)比特流依次代替模板中的x,得到:11100110 10110001 10001001,即E6 B1 89。
聰明的你肯定意識(shí)到我看到的Unicode碼不是這樣的啊,我看到的都是\u****
這樣的,那就再提一嘴轉(zhuǎn)譯序列,在C語(yǔ)言中,\u6C49
代表字符名稱為U+6C49
的Unicode碼。
你肯定還去去試我例子中的UTF-8編碼后的字節(jié)傳能不能轉(zhuǎn)化成漢字,于是你打開(kāi)網(wǎng)頁(yè),搜索UTF-8轉(zhuǎn)化,于是你快樂(lè)的把E6 B1 89
輸入進(jìn)去:得到的結(jié)果還是E6 B1 89
,你肯定有點(diǎn)懵逼,以為我在忽悠你,于是你打算取關(guān)我,于是你輸入”漢“字,于是你得到的結(jié)果為汉
,先別著急取消關(guān)注我,聽(tīng)我解釋啊:
其實(shí),和上面我們提到的為什么\u****
并不是純正的Unicode碼位對(duì)應(yīng)的十六進(jìn)制數(shù)差不多,我們看到的東西,都是經(jīng)過(guò)IDE或者Html等搞過(guò)的,所以它們會(huì)通過(guò)一些特殊的方法去簡(jiǎn)化或者說(shuō)標(biāo)志一種編碼方式。
在XML及其子集HTML采用UTF-8作為標(biāo)準(zhǔn)字集,理論上我們可以在各種支持XML標(biāo)準(zhǔn)的瀏覽器上顯示任何地區(qū)文字的網(wǎng)頁(yè),只要電腦本身安裝有合適的字體即可。可以利用&#nnn;的格式顯示特定的字符。nnn代表該字符的十進(jìn)制 Unicode 代碼。如果采用十六進(jìn)制代碼,在編碼之前加上x(chóng)字符即可。但部分舊版本的瀏覽器可能無(wú)法識(shí)別十六進(jìn)制代碼。是不是和你剛才的東西吻合了呢?
剛才取消關(guān)注的那個(gè)哥們兒,關(guān)注回來(lái)唄!
最后,我們來(lái)變個(gè)魔術(shù):
在 windows 電腦上新建一個(gè)記事本,輸入"聯(lián)通"兩個(gè)字之后,保存,關(guān)閉,然后再次打開(kāi),試一下,就是見(jiàn)證奇跡的時(shí)刻,不要懵逼,放開(kāi)你的想象力,你知道為什么嗎?