由于“字符編碼”這個(gè)話題牽涉到的歷史久遠(yuǎn)、機(jī)構(gòu)眾多、專業(yè)術(shù)語(yǔ)較多,所以本篇文章可能會(huì)略長(zhǎng),為了避免內(nèi)容過(guò)于枯燥,盡量用一種通俗易懂的語(yǔ)言來(lái)寫(xiě)這篇文章。
完成本篇文章的過(guò)程中參考和閱讀了大量的文章和文獻(xiàn),寫(xiě)本篇文章的目的一是讓大家對(duì)“字符編碼”能夠做一個(gè)較深的理解,二是希望給曾經(jīng)徘徊或正在徘徊在編碼困惑中的前端們一個(gè)很好的參考,搞清楚字符編碼問(wèn)題是前端萬(wàn)事之基石。
跟隨歷史的足跡看字符編碼
古代的通信方式
很久很久以前,人們之間的長(zhǎng)途通訊主要是用信鴿、騎馬送報(bào)、烽煙等方式進(jìn)行:
不過(guò)這些方式無(wú)不例外都是出奇的慢,同時(shí)也受天氣、地理等因素的影響。
世界第一條電報(bào)
直到1837年,世界第一條電報(bào)誕生,當(dāng)時(shí)美國(guó)科學(xué)家莫爾斯嘗試用一些“點(diǎn)”和“劃”來(lái)表示不同的字母、數(shù)字和標(biāo)點(diǎn)符號(hào),這套表示字符的方式也被稱為“摩爾斯電碼”:
世界第一臺(tái)計(jì)算機(jī)
再后來(lái)到了1946年,世界第一臺(tái)計(jì)算機(jī)誕生。發(fā)明計(jì)算機(jī)的同學(xué)們用8個(gè)晶體管的“通”或“斷”組合出一些狀態(tài)來(lái)表示世間萬(wàn)物,不過(guò)當(dāng)時(shí)的計(jì)算機(jī)有一間半教室那么大,六頭大象重,從現(xiàn)在看來(lái)這簡(jiǎn)直就是個(gè)怪物,但在當(dāng)時(shí)卻是震驚世界與改變世界的一項(xiàng)重要發(fā)明:
ASCII
8個(gè)晶體管的“通”或“斷”即可以代表一個(gè)字節(jié),剛開(kāi)始,計(jì)算機(jī)只在美國(guó)使用,所有的信息在計(jì)算機(jī)最底層都是以二進(jìn)制(“0”或“1”兩種不同的狀態(tài))的方式存儲(chǔ),而8位的字節(jié)一共可以組合出256(2的8次方)種狀態(tài),即256個(gè)字符,這對(duì)于當(dāng)時(shí)的美國(guó)已經(jīng)是足夠的了,他們嘗試把一些終端的動(dòng)作、字母、數(shù)字和符號(hào)用8位(bit)來(lái)組合:
0000 0000 ~ 0001 1111 共 33 種狀態(tài)用來(lái)表示終端的特殊動(dòng)作,如打印機(jī)中的響鈴為 0000 0111 ,當(dāng)打印機(jī)遇到 0000 0111 這樣的字節(jié)傳過(guò)來(lái)時(shí),打印機(jī)就開(kāi)始響鈴;
0010 0000 ~ 0010 1111 、 0011 1010~0110 0000 和 0111 1101 ~ 0111 1110 共 33 種狀態(tài)來(lái)表示英式標(biāo)點(diǎn)符號(hào),如 0011 1111 既代表英式問(wèn)號(hào)“?”;
0011 0000 ~ 0011 1001 共 10 種狀態(tài)來(lái)表示“0~9”10個(gè)阿拉伯?dāng)?shù)字;
0100 0001 ~ 0101 1010 和 0110 0001 ~ 0111 1010共 52種狀態(tài)來(lái)表示大小寫(xiě)英文字母;
自此,一共只用到了128種狀態(tài),即128個(gè)字符,剛好占用了一個(gè)字節(jié)中的后7位,共包括33個(gè)控制字符和95個(gè)可顯示字符,這一字符集被稱為ASCII(American Standard Code for Information Interchange,美國(guó)信息交換標(biāo)準(zhǔn)代碼),這一套字符集在1967年被正式公布。
講到這里,引出幾個(gè)基礎(chǔ)概念:
比特(bit):也可稱為“位”,是計(jì)算機(jī)信息中的最小單位,是 binary digit(二進(jìn)制數(shù)位) 的 縮寫(xiě),指二進(jìn)制中的一位
字節(jié)(Byte):計(jì)算機(jī)中信息計(jì)量的一種單位,一個(gè)位就代表“0”或“1”,每8個(gè)位(bit)組成一個(gè)字節(jié)(Byte)
字符(Character):文字與符號(hào)的總稱,可以是各個(gè)國(guó)家的文字、標(biāo)點(diǎn)符號(hào)、圖形符號(hào)、數(shù)字等
字符集(Character Set):是多個(gè)字符的集合
編碼(Encoding): 信息從一種形式或格式轉(zhuǎn)換為另一種形式的過(guò)程
解碼(decoding): 編碼的逆過(guò)程
字符編碼(Character Encoding): 按照何種規(guī)則存儲(chǔ)字符
現(xiàn)在我們來(lái)看我們文章開(kāi)頭提到的第一條電報(bào)的誕生,莫爾斯編碼中包含了大小寫(xiě)英文字母和數(shù)字等符號(hào)。
這里的每一個(gè)符號(hào)其實(shí)就是?字符?,
而這所有的字符的集合就叫做?字符集?,
“點(diǎn)”或“劃”與字符之間的對(duì)應(yīng)關(guān)系即可以稱為?字符編碼?。
電報(bào)的原理:
“點(diǎn)”對(duì)應(yīng)于短的電脈沖信號(hào),“劃”對(duì)應(yīng)于長(zhǎng)的電脈沖信號(hào),這些信號(hào)傳到對(duì)方,接收機(jī)把短的電脈沖信號(hào)翻譯成“點(diǎn)”,把長(zhǎng)的電脈沖信號(hào)轉(zhuǎn)換成“劃”,譯碼員根據(jù)這些點(diǎn)劃組合就可以譯成英文字母,從而完成了通信任務(wù)。
這里把字符表示為“點(diǎn)”或“劃”并對(duì)應(yīng)為電脈沖信號(hào)的過(guò)程既是?編碼?,
而譯碼員把接收機(jī)接收到的脈沖信號(hào)轉(zhuǎn)化成點(diǎn)劃后譯成字符的過(guò)程即為?解碼?。
而對(duì)于計(jì)算機(jī)誕生之后,只不過(guò)是將摩斯電碼中的“點(diǎn)”和“劃”換成了以8位字節(jié)二進(jìn)制流的方式表示,如數(shù)字1的二進(jìn)制流是0011 0001,對(duì)應(yīng)的十進(jìn)制流是49,十六進(jìn)制流是31。
EASCII
雖然剛開(kāi)始計(jì)算機(jī)只在美國(guó)使用,128個(gè)字符的確是足夠了,但隨著科技驚人的發(fā)展,歐洲國(guó)家也開(kāi)始使用上計(jì)算機(jī)了。不過(guò)128個(gè)字符明顯不夠呀,比如法語(yǔ)中,字母上方有注音符號(hào),于是,一些歐洲國(guó)家就決定,利用字節(jié)中閑置的最高位編入新的符號(hào)。比如,法語(yǔ)的é的二進(jìn)制流為1000 0010,這樣一來(lái),這些歐洲國(guó)家的編碼體系,可以表示最多256個(gè)字符了。
但是,這里又出現(xiàn)了新的問(wèn)題。不同的國(guó)家有不同的字母,因此,哪怕它們都使用256個(gè)符號(hào)的編碼方式,代表的字母卻不一樣。比如,1000 0010在法語(yǔ)編碼中代表了é,在希伯來(lái)語(yǔ)編碼中卻代表了字母Gimel (?),在俄語(yǔ)編碼中又會(huì)代表另一個(gè)符號(hào)。但是不管怎樣,所有這些編碼方式中,0–127表示的符號(hào)是一樣的,不一樣的只是128–255的這一段。
EASCII(Extended ASCII,延伸美國(guó)標(biāo)準(zhǔn)信息交換碼)由此應(yīng)運(yùn)而生,EASCII碼比ASCII碼擴(kuò)充出來(lái)的符號(hào)包括表格符號(hào)、計(jì)算符號(hào)、希臘字母和特殊的拉丁符號(hào):
GB2312
EASCII碼對(duì)于部分歐洲國(guó)家基本夠用了,但過(guò)后的不久,計(jì)算機(jī)便來(lái)到了中國(guó),要知道漢字是世界上包含符號(hào)最多并且也是最難學(xué)的文字。
據(jù)不完全統(tǒng)計(jì),漢字共包含了古文、現(xiàn)代文字等近10萬(wàn)個(gè)文字,就是我們現(xiàn)在日常用的漢字也有幾千個(gè),那么對(duì)于只包含256個(gè)字符的EASCII碼也難以滿足天朝的需求了。
于是?中國(guó)國(guó)家標(biāo)準(zhǔn)總局?(現(xiàn)已更名為?國(guó)家標(biāo)準(zhǔn)化管理委員會(huì)?)在1981年,正式制訂了中華人民共和國(guó)國(guó)家標(biāo)準(zhǔn)簡(jiǎn)體中文字符集,全稱《信息交換用漢字編碼字符集·基本集》,項(xiàng)目代號(hào)為GB 2312 或 GB 2312-80(GB為國(guó)標(biāo)漢語(yǔ)拼音的首字母),此套字符集于當(dāng)年的5月1日起正式實(shí)施。
包含字符:
共包含7445個(gè)字符,6763個(gè)漢字和682個(gè)其他字符(拉丁字母、希臘字母、日文平假名及片假名字母、俄語(yǔ)西里爾字母)
存儲(chǔ)方式:
基于EUC存儲(chǔ)方式,每個(gè)漢字及符號(hào)以兩個(gè)字節(jié)來(lái)表示,第一個(gè)字節(jié)為“高位字節(jié)”,第二個(gè)字節(jié)為“低位字節(jié)”
BIG5
要知道港澳臺(tái)同胞使用的是繁體字,而中國(guó)大陸制定的GB2312編碼并不包含繁體字,于是信息工業(yè)策進(jìn)會(huì)在1984年與臺(tái)灣13家廠商簽定“16位個(gè)人電腦套裝軟件合作開(kāi)發(fā)(BIG-5)計(jì)劃”,并開(kāi)始編寫(xiě)并推出BIG5標(biāo)準(zhǔn)。
之后推出的倚天中文系統(tǒng)則基于BIG5碼,并在臺(tái)灣地區(qū)取得了巨大的成功。在BIG5誕生后,大部分的電腦軟件都使用了Big5碼,BIG5對(duì)于以臺(tái)灣為核心的亞洲繁體漢字圈產(chǎn)生了久遠(yuǎn)的影響,以至于后來(lái)的window 繁體中文版系統(tǒng)在臺(tái)灣地區(qū)也基于BIG5碼進(jìn)行開(kāi)發(fā)。
包含字符:
共收錄13,060個(gè)漢字及441個(gè)符號(hào)
編碼方式:
用兩個(gè)字節(jié)來(lái)為每個(gè)字符編碼,第一個(gè)字節(jié)稱為“高位字節(jié)”,第二個(gè)字節(jié)稱為“低位字節(jié)”
Unicode
由來(lái):
在計(jì)算機(jī)進(jìn)入中國(guó)大陸的相同時(shí)期,計(jì)算機(jī)也迅速發(fā)展進(jìn)入了世界各個(gè)國(guó)家。
特別是對(duì)于亞洲國(guó)家而言,每個(gè)國(guó)家都有自己的文字,于是每個(gè)國(guó)家或地區(qū)都像中國(guó)大陸這樣去制定了自己的編碼標(biāo)準(zhǔn),以便能在計(jì)算機(jī)上正確顯示自己國(guó)家的符號(hào)。
但帶來(lái)的結(jié)果就是國(guó)家之間誰(shuí)也不懂別人的編碼,誰(shuí)也不支持別人的編碼,連大陸和臺(tái)灣這樣只相隔了150海里,都使用了不同的編碼體系。
于是,世界相關(guān)組織意識(shí)到了這個(gè)問(wèn)題,并開(kāi)始嘗試制定統(tǒng)一的編碼標(biāo)準(zhǔn),以便能夠收納世界所有國(guó)家的文字符號(hào)。
在前期有兩個(gè)嘗試這一工作的組織:
國(guó)際標(biāo)準(zhǔn)化組織(ISO)
統(tǒng)一碼聯(lián)盟
國(guó)際標(biāo)準(zhǔn)化組織(ISO)及國(guó)際電工委員會(huì)(IEC)于1984年聯(lián)合成立了ISO/IEC小組,主要用于開(kāi)發(fā)統(tǒng)一編碼項(xiàng)目;
而Xerox、Apple等軟件制造商則于1988年組成了統(tǒng)一碼聯(lián)盟,用于開(kāi)發(fā)統(tǒng)一碼項(xiàng)目。
兩個(gè)組織都在編寫(xiě)統(tǒng)一字符集,但后來(lái)他們發(fā)現(xiàn)各自在做相同的工作,同時(shí)世界上也不需要兩個(gè)不兼容的字符集,于是兩個(gè)組織就此合并了雙方的工作成果,并為創(chuàng)立一個(gè)單一編碼表而協(xié)同工作。
1991年,兩個(gè)組織共同的工作成果Unicode 1.0正式發(fā)布,不過(guò)Unicode 1.0并不包含CJK字符(即中日韓)。
版本歷史:
Unicode 1.0:1991年10月
Unicode 1.0.1:1992年6月
Unicode 1.1:1993年6月
Unicode 2.0:1997年7月
Unicode 2.1:1998年5月
Unicode 2.1.2:1998年5月
Unicode 3.0:1999年9月
Unicode 3.1:2001年3月
Unicode 3.2:2002年3月
Unicode 4.0:2003年4月
Unicode 4.0.1:2004年3月
Unicode 4.1:2005年3月
Unicode 5.0:2006年7月
Unicode 5.1:2008年4月
Unicode 5.2:2009年10月
Unicode 6.0:2010年10月
Unicode 4.1:2005年3月
Unicode 6.1:2012年1月31日
Unicode 6.2:2012年9月
ISO/IEC 8859
ISO/IEC小組在1984年成立后的第三年(即1987年)開(kāi)始啟動(dòng)ISO 8859標(biāo)準(zhǔn)的編寫(xiě),ISO 8859是一系列8位字符集的標(biāo)準(zhǔn),主要為世界各地的不同語(yǔ)言(除CJK)而單獨(dú)編寫(xiě)的字符集,一共定義了15個(gè)字符集:
ISO/IEC 8859-1:西歐語(yǔ)言
ISO/IEC 8859-2 :中歐語(yǔ)言
ISO/IEC 8859-3 :南歐語(yǔ)言
ISO/IEC 8859-4: 北歐語(yǔ)言
ISO/IEC 8859-5: 斯拉夫語(yǔ)
ISO/IEC 8859-6: 阿拉伯語(yǔ)
ISO/IEC 8859-7:希臘語(yǔ)
ISO/IEC 8859-8:希伯來(lái)語(yǔ)
ISO/IEC 8859-9:土耳其語(yǔ)
ISO/IEC 8859-10: 北日耳曼語(yǔ)
ISO/IEC 8859-11:泰語(yǔ)
ISO/IEC 8859-13: 波羅的語(yǔ)族
ISO/IEC 8859-14: 凱爾特語(yǔ)族
ISO/IEC 8859-15:西歐語(yǔ)言,收錄芬蘭語(yǔ)字母和大寫(xiě)法語(yǔ)重音字母,以及歐元(€)符號(hào)
ISO/IEC 8859-16 :東南歐語(yǔ)言,主要供羅馬尼亞語(yǔ)使用,并加入歐元(€)符號(hào)
其中ISO/IEC 8859-1至ISO/IEC 8859-4四個(gè)項(xiàng)目早在1982年就已經(jīng)編寫(xiě)出來(lái),只不過(guò)是由ANSI與ECMA合作完成,并于1985年正式公布,ISO/IEC小組成立后,這一成果被其收錄,并改名為ISO/IEC 8859 前四個(gè)項(xiàng)目。
大家其實(shí)發(fā)現(xiàn)以上15個(gè)字符集中并沒(méi)有代號(hào)為“ISO/IEC 8859 -12”的字符集,據(jù)說(shuō)-12號(hào)本來(lái)是預(yù)留給印度天城體梵文的,但后來(lái)卻擱置了(阿三有了自己的編碼-ISCII)。由于英語(yǔ)沒(méi)有任何重音字母,故可使用以上十五個(gè)字符集中的任何一個(gè)來(lái)表示。
ISO/IEC 10646 / UCS
1993年,ISO/IEC 10646標(biāo)準(zhǔn)第一次發(fā)表,ISO/IEC 10646是ISO 646的擴(kuò)展,定義了1個(gè)31位的字符集。ISO 10646標(biāo)準(zhǔn)中定義的字符集為UCS,UCS是Universal Character Set的縮寫(xiě),中文譯作通用字符集。
版本:
ISO/IEC 10646-1:第一次發(fā)表于1993年,現(xiàn)在的公開(kāi)版本是2000年發(fā)表的ISO/IEC 10646-1:2000。
ISO/IEC 10646-2:在2001年發(fā)表。
包含字符:
最初的ISO 10646-1:1993的編碼標(biāo)準(zhǔn),即Unicode 1.1,收錄中國(guó)大陸、臺(tái)灣、日本及韓國(guó)通用字符集的漢字共計(jì)20,902個(gè),當(dāng)然每個(gè)版本的Unicode標(biāo)準(zhǔn)的字符集所包含的字符數(shù)不盡相同,UCS 包含了已知語(yǔ)言的所有字符,除了拉丁語(yǔ)、希臘語(yǔ)、斯拉夫語(yǔ)、希伯來(lái)語(yǔ)、阿拉伯語(yǔ)、亞美尼亞語(yǔ)、格魯吉亞語(yǔ),還包括中文、日文、韓文這樣的方塊文字,此外還包括了大量的圖形、印刷、數(shù)學(xué)、科學(xué)符號(hào)。
UCS給每個(gè)字符分配一個(gè)唯一的代碼,并且賦予了一個(gè)正式的名字,通常在表示一個(gè)Unicode值的十六進(jìn)制數(shù)的前面加上“U+”,例如“U+0041”代表字符“A”。
編碼方案:
UCS僅僅是一個(gè)超大的字符集,關(guān)于UCS制定的編碼方案有兩種:UCS-2和UCS-4,Unicode默認(rèn)以UCS-2編碼。
顧名思義,UCS-2就是用兩個(gè)字節(jié)編碼,UCS-4就是用4個(gè)字節(jié)(實(shí)際上只用了31位,最高位必須為0)編碼。那么UCS-2其實(shí)可以容納的字符數(shù)為65536(2的16次方),而UCS-4可以容納的字符數(shù)為2147483648(2的31次方)。其實(shí)對(duì)于UCS-2已經(jīng)是完全夠用了,基本可以包含世界所有國(guó)家的常用文字,如果需要考慮一些偏僻字,那么UCS-4則絕對(duì)可以滿足了,21億個(gè)字符哪怕是整個(gè)宇宙也夠用了吧!
UTF
Unicode 誕生,隨之而來(lái)的計(jì)算機(jī)網(wǎng)絡(luò)也發(fā)展了起來(lái),Unicode 如何在網(wǎng)絡(luò)上傳輸也是一個(gè)必須考慮的問(wèn)題,于是在1992年,面向網(wǎng)絡(luò)傳輸?shù)腢TF標(biāo)準(zhǔn)出現(xiàn)了。
UTF是Unicode Transformation Format的縮寫(xiě),中文譯作Unicode轉(zhuǎn)換格式。其實(shí)我們從現(xiàn)在可以把Unicode看作是一個(gè)標(biāo)準(zhǔn)或組織,而UCS就是一個(gè)字符集,那么UCS在網(wǎng)絡(luò)中的傳輸標(biāo)準(zhǔn)就是UTF了。
前面提到了UCS的編碼實(shí)現(xiàn)方式為UCS-2和UCS-4,即要么是每個(gè)字符為2個(gè)字節(jié),要么是4個(gè)字節(jié)。如果一個(gè)僅包含基本7位ASCII字符的 Unicode文件,每個(gè)字符都使用2字節(jié)的原Unicode編碼傳輸,其第一字節(jié)的8位始終為0,這就造成了比較大的浪費(fèi)。但是,聰明的人們發(fā)明了 UTF-8,UTF-8采用可變字節(jié)編碼,這樣可以大大節(jié)省帶寬,并增加網(wǎng)絡(luò)傳輸效率。
UTF-8
使用1~4個(gè)字節(jié)為每個(gè)UCS中的字符編碼:
128個(gè)ASCII字符只需一個(gè)字節(jié)編碼(Unicode范圍由U+0000至U+007F)
拉丁文、希臘文、西里爾字母、亞美尼亞語(yǔ)、希伯來(lái)文、阿拉伯文、敘利亞文及它拿字母需要二個(gè)字節(jié)編碼(Unicode范圍由U+0080至U+07FF)
大部分國(guó)家的常用字(包括中文)使用三個(gè)字節(jié)編碼
其他極少使用的生僻字符使用四字節(jié)編碼
UTF-16/UCS-2
UCS-2的父集,使用2個(gè)或4個(gè)字節(jié)來(lái)為每個(gè)UCS中的字符編碼:
128個(gè)ASCII字符需兩個(gè)字節(jié)編碼
其他字符使用四個(gè)字節(jié)編碼
UTF-32/UCS-4
等同于UCS-4,對(duì)于所有字符都使用四個(gè)字節(jié)來(lái)編碼
GB13000
前面提到了Unicode的迅速發(fā)展,至1993年時(shí),包含CJK的Unicode 1.1已經(jīng)發(fā)布了,天朝的ZF也意識(shí)到了需要一個(gè)更大的字符集來(lái)走向世界,于是在同一年,中國(guó)大陸制定了幾乎等同于Unicode1.1的 GB13000.1-93國(guó)家編碼標(biāo)準(zhǔn)(簡(jiǎn)稱GB13000)。是的,你沒(méi)聽(tīng)錯(cuò),中華人民共和國(guó)信息產(chǎn)業(yè)部把Unicode里的所有東東拿過(guò)來(lái),然后自己重新修訂發(fā)布了下,改為了國(guó)家標(biāo)準(zhǔn)GB13000。此標(biāo)準(zhǔn)等同于 ISO/IEC 10646.1:1993和Unicode 1.1。
GBK
1995年,在GB13000誕生后不久,中國(guó)教育科研網(wǎng)(NCFC)與美國(guó)NCFnet直接聯(lián)網(wǎng),這一天是中國(guó)被國(guó)際承認(rèn)為開(kāi)始有網(wǎng)際網(wǎng)路的時(shí)間。此后網(wǎng)絡(luò)正式開(kāi)始在中國(guó)大陸接通,個(gè)人計(jì)算機(jī)開(kāi)始在中國(guó)流行,雖然當(dāng)時(shí)只是高富帥才消費(fèi)得起的產(chǎn)品。中國(guó)是一個(gè)十幾億人口的大國(guó),微軟意識(shí)到了中國(guó)是一個(gè)巨大的市場(chǎng),當(dāng)時(shí)的微軟也將自己的操作系統(tǒng)市場(chǎng)布局進(jìn)中國(guó),進(jìn)入中國(guó)隨之而來(lái)要解決的就是系統(tǒng)的編碼兼容問(wèn)題。
之前的國(guó)家編碼標(biāo)準(zhǔn)GB 2312,基本滿足了漢字的計(jì)算機(jī)處理需要,它所收錄的漢字已經(jīng)覆蓋中國(guó)大陸99.75%的使用頻率。但對(duì)于人名、古漢語(yǔ)等方面出現(xiàn)的罕用字和繁體字,GB 2312不能處理,因此微軟利用了GB2312中未使用的編碼空間,收錄了GB13000中的所有字符制定了漢字內(nèi)碼擴(kuò)展規(guī)范GBK(K為漢語(yǔ)拼音 Kuo Zhan中“擴(kuò)”字的首字母)。所以這一關(guān)系其實(shí)是大陸把Unicode1.1借鑒過(guò)來(lái)改名為了GB13000,而微軟則利用GB2312中未使用的編碼空間收錄GB13000制定了GBK。所以GBK是向下完全兼容GB2312的。
包含字符:
共收錄21886個(gè)字符, 其中漢字21003個(gè), 字符883個(gè)
編碼方式:
GBK只不過(guò)是把GB2312中未使用的空間,編碼了其他字符,所以GBK同樣是用兩個(gè)字節(jié)為每個(gè)字符進(jìn)行編碼。
GB18030
微軟到了99年前后,說(shuō)GBK已經(jīng)落伍了,現(xiàn)在流行UTF-8標(biāo)準(zhǔn),準(zhǔn)備全盤(pán)轉(zhuǎn)換成UTF-8,但中國(guó)ZF不是吃素的,編寫(xiě)并強(qiáng)制推出了 GB18030標(biāo)準(zhǔn)。GB18030的誕生還有一個(gè)原因是GBK只包含了大部分的漢字和繁體字等,我們的少數(shù)民族兄弟根本木有考慮!中國(guó)有56個(gè)民族,其中有12個(gè)民族有自己的文字,那怎么辦呢?在2000年,電子工業(yè)標(biāo)準(zhǔn)化研究所起草了GB18030標(biāo)準(zhǔn),項(xiàng)目代號(hào)“GB 18030-2000”,全稱《信息技術(shù)-信息交換用漢字編碼字符集-基本集的擴(kuò)充》。此標(biāo)準(zhǔn)推出后,在中國(guó)大陸之后的所售產(chǎn)品必須強(qiáng)制支持GB18030標(biāo)準(zhǔn),不然不得賣!(這招挺狠的 – -#)
版本:
GB 18030-2000
GB 18030-2005
包含字符:
GB18030收錄了GBK中的所有字符,并將Unicode中其他中文字符(少數(shù)民族文字、偏僻字)也一并收錄進(jìn)來(lái)重新編碼。其中GB 18030-2000共收錄27533個(gè)漢字,而GB 18030-2005共包含70244個(gè)漢字。
編碼方式:
采用多字節(jié)編碼,每個(gè)字符由1或2或4個(gè)字節(jié)進(jìn)行編碼
前端眼中的字符編碼
前面我們穿越回過(guò)去對(duì)字符編碼做了下了解,那么這些字符編碼跟我們到底有啥關(guān)系?
基本原理:
當(dāng)我們打開(kāi)編輯器coding時(shí),按下ctrl+s的那一刻,其實(shí)等于是將自己的工作成果存儲(chǔ)進(jìn)了計(jì)算機(jī),而這里最關(guān)鍵的是我們以什么字符編碼來(lái)進(jìn)行存儲(chǔ),我們以intellij編輯器為例:
我們?cè)诰帉?xiě)此文檔時(shí),是以UTF-8編碼方式進(jìn)行coding,當(dāng)我們按下ctrl+s時(shí),則此文檔以u(píng)tf-8編碼方式存儲(chǔ)進(jìn)了計(jì)算機(jī)(右下角的UTF-8),而head區(qū)域中的的作用則是告訴瀏覽器此文檔以u(píng)tf-8編碼方式編碼。
我們此時(shí)用Hex編輯器打開(kāi)這個(gè)文件,來(lái)看看他的二進(jìn)制流:
其中紅框標(biāo)注出的即為“小?!眱蓚€(gè)中文字的二進(jìn)制流,第一個(gè)為”11100101 10110000 10001111″轉(zhuǎn)化為十六進(jìn)制則為“E5B08F”,第二個(gè)為“10110101 10110111 00001101”轉(zhuǎn)化為十六進(jìn)制為“E6B5B7”,而當(dāng)我們?nèi)ゲ樵僓TF-8的碼表時(shí)發(fā)現(xiàn)“E5B08F”對(duì)應(yīng)的字符為“小”,“E6B5B7”對(duì)應(yīng)的字符則為“?!?,至此當(dāng)我們用瀏覽器進(jìn)行預(yù)覽頁(yè)面時(shí),由于瀏覽器同樣以UTF-8方式對(duì)此頁(yè)面進(jìn)行解碼,“小?!眱蓚€(gè)字則可以被正確的顯示出來(lái)。
亂碼是個(gè)XX
做過(guò)前端的基本都遇到過(guò)亂碼問(wèn)題吧?好吧,下面就帶大家來(lái)揭開(kāi)這一神秘的面紗。
我們用notepad打開(kāi)上面的文件,并重新以GBK方式編碼,然后用intellij打開(kāi)后:
亂了有木有!居然變成了“C??”,木有道理呀!我在用notepad編輯文件時(shí)采用的是gbk編碼,而頭部申明的也是gbk,本身notepad打開(kāi)也是正常,但用intellij打開(kāi)卻亂了!
罪魁禍?zhǔn)祝壕庉嬈髂J(rèn)編碼。每個(gè)編輯器都會(huì)有默認(rèn)編碼,如果沒(méi)有為一個(gè)項(xiàng)目單獨(dú)設(shè)置過(guò)默認(rèn)編碼,打開(kāi)一個(gè)單獨(dú)的文件,編輯器往往以自己的默認(rèn)編碼去解碼這個(gè)文件,如上圖,我們的inellij編輯器的默認(rèn)是UTF-8解碼,而文件是GBK編碼方式,那么打開(kāi)肯定就是亂的拉。
所以編輯器也是一個(gè)因素,DW則可以智能判斷文件的編碼方式,上述文件用DW打開(kāi)并不會(huì)亂碼,而intellij可能對(duì)中文的支持并不是很好,所以還不能智能判斷中文編碼,默認(rèn)以UTF-8解碼(當(dāng)然默認(rèn)編碼自己是可以修改的)。
很多讀者可能還有一個(gè)疑問(wèn),為啥亂碼出來(lái)的是“C??”?
其實(shí)原理已在上面的基本原理中做過(guò)介紹,即編輯器ctrl+s存進(jìn)計(jì)算機(jī)時(shí)是GBK,但嘗試用utf-8來(lái)解析,對(duì)應(yīng)的utf-8中的碼表中卻找到了“C??”,感興趣的同學(xué)可以自己研究下。
我們現(xiàn)在將文件重新編輯,即編輯時(shí)采用GBK,但頭部申明為UTF-8:
然后用瀏覽器打開(kāi)后,就是這樣了:
亂了有木有!這個(gè)其實(shí)和編輯器打開(kāi)一個(gè)文件亂碼的原理是一致的:即編輯器編碼時(shí)所采用的字符編碼和解碼時(shí)所采用的字符編碼不一致。上述栗子,我們?cè)赾oding時(shí)采用的是GBK編碼,但頭部卻告訴瀏覽器這個(gè)文檔是UTF-8編碼,那么瀏覽器在用UTF-8解碼時(shí)就會(huì)出現(xiàn)了亂碼。
申明編碼的方式
我們?cè)赾oding時(shí)需要告訴瀏覽器自己的文件采用了什么字符編碼,下面列出一些常見(jiàn)的方法:
//html5
//html4 xhtml
我們可以在head區(qū)域的meta元素中為整個(gè)頁(yè)面申明編碼方式
,也可以為單獨(dú)的外鏈文件申明編碼方式(link/script等元素)。問(wèn)題是如果頁(yè)面頭部和外鏈文件中只有部分申明或者全部申明,那么對(duì)應(yīng)的到底是以什么方式解碼呢?這里就有一個(gè)優(yōu)先級(jí)的問(wèn)題,具體的判定關(guān)系如下:
通過(guò)上述判定,我們其實(shí)可以發(fā)現(xiàn),一個(gè)頁(yè)面中優(yōu)先級(jí)最高的其實(shí)是服務(wù)端的編碼設(shè)置,如果一旦服務(wù)端設(shè)置了編碼A,那么頁(yè)面即以A來(lái)解析。
目前Google采用的是這一做法,這樣的傳輸效率會(huì)更高,不需要在頭部額外再單獨(dú)申明編碼,但這樣其實(shí)也有一定的風(fēng)險(xiǎn),除了需要有一個(gè)嚴(yán)謹(jǐn)?shù)木幋a規(guī)范,還需要確保服務(wù)器上的頁(yè)面都保持同一編碼,一旦不一致就會(huì)造成亂碼,所以目前這一方案在國(guó)內(nèi)用的并不多。
其他的,如果外鏈資源設(shè)置了編碼C,那么即以C來(lái)解析,無(wú)論服務(wù)端和頭部是否申明編碼。
但必須要提醒大家的是:申明的編碼只是告訴瀏覽器相關(guān)的內(nèi)容是以什么方案去解碼,并不是這一部分內(nèi)容就采用了這個(gè)編碼。所以大家在coding時(shí)的編碼一定要確保和你申明的保持統(tǒng)一,不然就會(huì)出現(xiàn)亂碼的問(wèn)題。
BOM是個(gè)神馬
BOM是byte-order mark的縮寫(xiě),為Unicode標(biāo)準(zhǔn)為了用來(lái)區(qū)分一個(gè)文件是UTF-8還是UTF-16或UTF-32編碼方式的記號(hào),又稱字節(jié)序。
UTF-8以單字節(jié)為編碼單元,并沒(méi)有字節(jié)序的問(wèn)題,而UTF-16以兩個(gè)字節(jié)為編碼單元,在解釋一個(gè)UTF-16文本前,首先要弄清楚每個(gè)編碼單元的字節(jié)序。例如“奎”的Unicode編碼是594E,“乙”的Unicode編碼是4E59。如果我們收到UTF-16字節(jié)流“594E”,那么這是 “奎”還是“乙”?這是UTF-16文件開(kāi)頭的BOM就有作用了。
采用Unicode編碼方式的文件如果開(kāi)頭出現(xiàn)了“FEFF”,“FEFF”在UCS中是不存在的字符,也叫做“ZERO WIDTH NO-BREAK SPACE”,那么就表明這個(gè)文件的字節(jié)流是Big-Endian(高字節(jié)在前)的;如果收到“FFFE”,就表明字節(jié)流是Little- Endian(低字節(jié)在前)。
在UTF-8文件中放置BOM主要是微軟的習(xí)慣,BOM其實(shí)是為UTF-16和UTF-32準(zhǔn)備的,微軟在UTF-8使用BOM是因?yàn)檫@樣可以把UTF-8和ASCII等編碼明確區(qū)分開(kāi),但這樣的文件在Window以外的其他操作系統(tǒng)里會(huì)帶來(lái)問(wèn)題。
我們以Window下的文本文件為例:
在保存時(shí)可以選擇ANSI、Unicode、Unicode big endian和UTF-8四種編碼方式。
其中ANSI是默認(rèn)的編碼方式,對(duì)于英文文件是ASCII編碼,對(duì)于簡(jiǎn)體中文文件是GB2312編碼(只針對(duì)Windows簡(jiǎn)體中文版,如果是繁體中文版會(huì)采用Big5碼);
Unicode其實(shí)是UTF-16 endian big編碼方式,這個(gè)把帶有BOM的小端序UTF-16稱作Unicode而又不詳細(xì)說(shuō)明,也是微軟的習(xí)慣;
而Unicode big endian則是帶有BOM的大端序編碼方式
目前UTF-16通常用于系統(tǒng)文件的編碼,而UTF-32由于對(duì)每個(gè)字符都采用四個(gè)字節(jié)編碼,所以現(xiàn)在互聯(lián)網(wǎng)中大部分都采用UTF-8來(lái)進(jìn)行編碼傳輸。
關(guān)于未來(lái)的展望
概述
(圖:中國(guó)地區(qū)ALEXA排名前20的站點(diǎn)所采用的編碼占比)
(圖:騰訊互娛所有業(yè)務(wù)所采用的編碼占比)
左圖表明GB2312、GBK與UTF-8編碼三分天下,而右圖顯示騰訊互娛的業(yè)務(wù)大多數(shù)采用了GB2312,零星的采用了其他編碼??偟木褪遣煌淖址幋a方案基本都存在了,而這也與各公司業(yè)務(wù)的歷史原因也有一定的關(guān)系。
當(dāng)我們?cè)陧?xiàng)目的最初期時(shí)采用了一種非Unicode編碼方案時(shí),隨著業(yè)務(wù)的壯大,積累的頁(yè)面越來(lái)越多,到后期想去改成Unicode編碼方案,就會(huì)擔(dān)心出錯(cuò)的問(wèn)題,所以現(xiàn)在大多數(shù)公司都采用了延用初期編碼的方式,如淘寶,騰訊互娛等,以及四大門(mén)戶。
擺在眼前的問(wèn)題
可是,某一天了,我們的網(wǎng)站用戶港澳臺(tái)用戶也變多了,我們需要支持繁體怎么辦?
某一天,我們的業(yè)務(wù)拓展到東南亞了,我們需要我們的網(wǎng)站也能支持那些國(guó)家的語(yǔ)言怎么辦?
如今,國(guó)內(nèi)大多數(shù)公司采用的方案是,為相應(yīng)的環(huán)境單獨(dú)做一套編碼文件,如 http://big5.china.com.cn/ ,又如 http://big5.qidian.com。
再比如,哪一天了,我們的網(wǎng)站需要支持少數(shù)民族的語(yǔ)言怎么辦?
難道像央視這樣切成圖么?
嗯,這一切都只是暫時(shí)的方案,但人一旦變得懶起來(lái),就不愿意去改變一些東西,就比如UTF-8。
擁抱國(guó)際化標(biāo)準(zhǔn)
一切就等著我們敞開(kāi)胸懷去擁抱,而不是沉浸在過(guò)去的喜悅中。最終的編碼方案決定權(quán)在我們自己手里,改變,只是時(shí)間的問(wèn)題。
本文由企業(yè)網(wǎng)絡(luò)服務(wù)平臺(tái)中億智企云網(wǎng)商學(xué)院為你提供,關(guān)于更多相關(guān)資訊,請(qǐng)瀏覽我們的企業(yè)網(wǎng)絡(luò)服務(wù)平臺(tái)官網(wǎng)http://chinadlxs668.top,或是撥打我們的全國(guó)服務(wù)熱線:400-698-5980!
全國(guó)客戶服務(wù)免費(fèi)熱線:15874991942
在線客服:2225973985
每天前10名咨詢有好禮
智企云 版權(quán)所有 ? 2016-2018 湘ICP備11017552號(hào)
地址:長(zhǎng)沙市高新開(kāi)發(fā)區(qū)尖山路39號(hào)中電軟件園總部大樓6樓
Copyright ? 2015-2024 智企云 All Rights Reserved. 湘ICP備11017552號(hào) 技術(shù)支持:中億智企云
湘公網(wǎng)安備43019002000674號(hào) 客服熱線:15874991942 公司地址:長(zhǎng)沙市高新開(kāi)發(fā)區(qū)尖山路39號(hào)中電軟件園總部大樓6樓