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