資源描述:
《深入了解字符集,徹底消除亂碼問(wèn)題》由會(huì)員上傳分享,免費(fèi)在線閱讀,更多相關(guān)內(nèi)容在行業(yè)資料-天天文庫(kù)。
1、字符編碼的問(wèn)題看似很小,經(jīng)常被技術(shù)人員忽視,但是很容易導(dǎo)致一些莫名其妙的問(wèn)題。這里總結(jié)了一下字符編碼的一些普及性的知識(shí),希望對(duì)大家有所幫助。還是得從ASCII碼說(shuō)起說(shuō)到字符編碼,不得不說(shuō)ASCII碼的簡(jiǎn)史。計(jì)算機(jī)一開始發(fā)明的時(shí)候是用來(lái)解決數(shù)字計(jì)算的問(wèn)題,后來(lái)人們發(fā)現(xiàn),計(jì)算機(jī)還可以做更多的事,例如文本處理。但由于計(jì)算機(jī)只識(shí)“數(shù)”,因此人們必須告訴計(jì)算機(jī)哪個(gè)數(shù)字來(lái)代表哪個(gè)特定字符,例如65代表字母‘A’,66代表字母‘B’,以此類推。但是計(jì)算機(jī)之間字符-數(shù)字的對(duì)應(yīng)關(guān)系必須得一致,否則就會(huì)造成同一段數(shù)字在不同計(jì)算機(jī)上顯示出來(lái)的字符不一樣。因此美國(guó)
2、國(guó)家標(biāo)準(zhǔn)協(xié)會(huì)ANSI制定了一個(gè)標(biāo)準(zhǔn),規(guī)定了常用字符的集合以及每個(gè)字符對(duì)應(yīng)的編號(hào),這就是ASCII字符集(CharacterSet),也稱ASCII碼。當(dāng)時(shí)的計(jì)算機(jī)普遍使用8比特字節(jié)作為最小的存儲(chǔ)和處理單元,加之當(dāng)時(shí)用到的字符也很少,26個(gè)大小寫英文字母還有數(shù)字再加上其他常用符號(hào),也不到100個(gè),因此使用7個(gè)比特位就可以高效的存儲(chǔ)和處理ASCII碼,剩下最高位1比特被用作一些通訊系統(tǒng)的奇偶校驗(yàn)。注意,字節(jié)代表系統(tǒng)能夠處理的最小單位,不一定是8比特。只是現(xiàn)代計(jì)算機(jī)的事實(shí)標(biāo)準(zhǔn)就是用8比特來(lái)代表一個(gè)字節(jié)。在很多技術(shù)規(guī)格文獻(xiàn)中,為了避免產(chǎn)生歧義,更傾
3、向于使用8位組(Octet)而不是字節(jié)(Byte)這個(gè)術(shù)語(yǔ)來(lái)強(qiáng)調(diào)8個(gè)比特的二進(jìn)制流。下文中為了便于理解,我會(huì)延用大家熟悉的“字節(jié)”這個(gè)概念。ASCII字符集由95個(gè)可打印字符(0x20-0x7E)和33個(gè)控制字符(0x00-0x19,0x7F)組成??纱蛴∽址糜陲@示在輸出設(shè)備上,例如熒屏或者打印紙上,控制字符用于向計(jì)算機(jī)發(fā)出一些特殊指令,例如0x07會(huì)讓計(jì)算機(jī)發(fā)出嗶的一聲,0x00通常用于指示字符串的結(jié)束,0x0D和0x0A用于指示打印機(jī)的打印針頭退到行首(回車)并移到下一行(換行)。那時(shí)候的字符編解碼系統(tǒng)非常簡(jiǎn)單,就是簡(jiǎn)單的查表過(guò)程。例
4、如將字符序列編碼為二進(jìn)制流寫入存儲(chǔ)設(shè)備,只需要在ASCII字符集中依次找到字符對(duì)應(yīng)的字節(jié),然后直接將該字節(jié)寫入存儲(chǔ)設(shè)備即可。解碼二進(jìn)制流的過(guò)程也是類似。OEM字符集的衍生當(dāng)計(jì)算機(jī)開始發(fā)展起來(lái)的時(shí)候,人們逐漸發(fā)現(xiàn),ASCII字符集里那可憐的128個(gè)字符已經(jīng)不能再滿足他們的需求了。人們就在想,一個(gè)字節(jié)能夠表示的數(shù)字(編號(hào))有256個(gè),而ASCII字符只用到了0x00~0x7F,也就是占用了前128個(gè),后面128個(gè)數(shù)字不用白不用,因此很多人打起了后面這128個(gè)數(shù)字的主意。可是問(wèn)題在于,很多人同時(shí)有這樣的想法,但是大家對(duì)于0x80-0xFF這后面的
5、128個(gè)數(shù)字分別對(duì)應(yīng)什么樣的字符,卻有各自的想法。這就導(dǎo)致了當(dāng)時(shí)銷往世界各地的機(jī)器上出現(xiàn)了大量各式各樣的OEM字符集。下面這張表是IBM-PC機(jī)推出的其中一個(gè)OEM字符集,字符集的前128個(gè)字符和ASCII字符集的基本一致(為什么說(shuō)基本一致呢,是因?yàn)榍?2個(gè)控制字符在某些情況下會(huì)被IBM-PC機(jī)當(dāng)作可打印字符解釋),后面128個(gè)字符空間加入了一些歐洲國(guó)家用到的重音字符,以及一些用于畫線條畫的字符。事實(shí)上,大部分OEM字符集是兼容ASCII字符集的,也就是說(shuō),大家對(duì)于0x00~0x7F這個(gè)范圍的解釋基本是相同的,而對(duì)于后半部分0x80~0xF
6、F的解釋卻不一定相同。甚至有時(shí)候同樣的字符在不同OEM字符集中對(duì)應(yīng)的字節(jié)也是不同的。不同的OEM字符集導(dǎo)致人們無(wú)法跨機(jī)器交流各種文檔。例如職員甲發(fā)了一封簡(jiǎn)歷résumés給職員乙,結(jié)果職員乙看到的卻是rsums,因?yàn)楱ψ址诼殕T甲機(jī)器上的OEM字符集中對(duì)應(yīng)的字節(jié)是0x82,而在職員乙的機(jī)器上,由于使用的OEM字符集不同,對(duì)0x82字節(jié)解碼后得到的字符卻是。多字節(jié)字符集(MBCS)和中文字符集上面我們提到的字符集都是基于單字節(jié)編碼,也就是說(shuō),一個(gè)字節(jié)翻譯成一個(gè)字符。這對(duì)于拉丁語(yǔ)系國(guó)家來(lái)說(shuō)可能沒有什么問(wèn)題,因?yàn)樗麄兺ㄟ^(guò)擴(kuò)展第8個(gè)比特,就可以得到
7、256個(gè)字符了,足夠用了。但是對(duì)于亞洲國(guó)家來(lái)說(shuō),256個(gè)字符是遠(yuǎn)遠(yuǎn)不夠用的。因此這些國(guó)家的人為了用上電腦,又要保持和ASCII字符集的兼容,就發(fā)明了多字節(jié)編碼方式,相應(yīng)的字符集就稱為多字節(jié)字符集。例如中國(guó)使用的就是雙字節(jié)字符集編碼(DBCS,DoubleByteCharacterSet)。對(duì)于單字節(jié)字符集來(lái)說(shuō),代碼頁(yè)中只需要有一張碼表即可,上面記錄著256個(gè)數(shù)字代表的字符。程序只需要做簡(jiǎn)單的查表操作就可以完成編解碼的過(guò)程。代碼頁(yè)是字符集編碼的具體實(shí)現(xiàn),你可以把他理解為一張“字符-字節(jié)”映射表,通過(guò)查表實(shí)現(xiàn)“字符-字節(jié)”的翻譯。下面會(huì)有更詳細(xì)
8、的描述。而對(duì)于多字節(jié)字符集,代碼頁(yè)中通常會(huì)有很多碼表。那么程序怎么知道該使用哪張碼表去解碼二進(jìn)制流呢?答案是,根據(jù)第一個(gè)字節(jié)來(lái)選擇不同的碼表進(jìn)行解析。例如目前最常用的中文字符集G