java編碼中的中文問(wèn)題是一個(gè)老生常談的問(wèn)題了,每次遇到中文亂碼LZ要么是按照以前的經(jīng)驗(yàn)修改,要么則是baidu.com來(lái)解決問(wèn)題。閱讀許多關(guān)于中文亂碼的解決辦法的博文后,發(fā)現(xiàn)對(duì)于該問(wèn)題我們都(更加包括我自己)沒(méi)有一個(gè)清晰明了的認(rèn)識(shí),于是LZ想通過(guò)這系列博文(估計(jì)只有幾篇)來(lái)徹底分析、解決java中文亂碼問(wèn)題,如有錯(cuò)誤之處望各位同仁指出!當(dāng)然,此系列博文并非LZ完全原創(chuàng),都是在前輩基礎(chǔ)上總結(jié),歸納,如果雷同純屬借鑒……
對(duì)于計(jì)算機(jī)而言,它僅認(rèn)識(shí)兩個(gè)0和1,不管是在內(nèi)存中還是外部存儲(chǔ)設(shè)備上,我們所看到的文字、圖片、視頻等等“數(shù)據(jù)”在計(jì)算機(jī)中都是已二進(jìn)制形式存在的。不同字符對(duì)應(yīng)二進(jìn)制數(shù)的規(guī)則,就是字符的編碼。字符編碼的集合稱為字符集。
在早期的計(jì)算機(jī)系統(tǒng)中,使用的字符是非常少的,他們只包括26個(gè)英文字母、數(shù)字符號(hào)和一些常用符號(hào),對(duì)于這些字符進(jìn)行編碼,用1個(gè)字節(jié)就足夠了,但是隨著計(jì)算機(jī)的不斷發(fā)展,為了適應(yīng)全世界其他各國(guó)民族的語(yǔ)言,這些少得可憐的字符編碼肯定是不夠的。于是人們提出了UNICODE編碼,它采用雙字節(jié)編碼,兼容英文字符和其他國(guó)家民族的雙字節(jié)字符編碼。
每個(gè)國(guó)家為了統(tǒng)一編碼都會(huì)規(guī)定該國(guó)家/地區(qū)計(jì)算機(jī)信息交換用的字符集編碼,為了解決本地字符信息的計(jì)算機(jī)處理,于是出現(xiàn)了各種本地化版本,引進(jìn)LANG, Codepage 等概念。現(xiàn)在大部分具有國(guó)際化特征的軟件核心字符處理都是以 Unicode 為基礎(chǔ)的,在軟件運(yùn)行時(shí)根據(jù)當(dāng)時(shí)的 Locale/Lang/Codepage 設(shè)置確定相應(yīng)的本地字符編碼設(shè)置,并依此處理本地字符。在處理過(guò)程中需要實(shí)現(xiàn) Unicode 和本地字符集的相互轉(zhuǎn)換。
同然,java內(nèi)部采用的就是Unicode編碼,所以在java運(yùn)行的過(guò)程中就必然存在從Unicode編碼與相應(yīng)的計(jì)算機(jī)操作系統(tǒng)或者瀏覽器支持的編碼格式相互轉(zhuǎn)化的過(guò)程,這個(gè)轉(zhuǎn)換的過(guò)程有一系列的步驟,如果某個(gè)步驟出現(xiàn)錯(cuò)誤,則輸出的文字就會(huì)是亂碼。
所以產(chǎn)生java亂碼的問(wèn)題就在于JVM與對(duì)應(yīng)的操作系統(tǒng)/瀏覽器進(jìn)行編碼格式轉(zhuǎn)換時(shí)出現(xiàn)了錯(cuò)誤。
其實(shí)要解決java亂碼問(wèn)題的方法還是比較簡(jiǎn)單的,但是要究其原因,理解背后的原理還是需要了解
其實(shí)解決 JAVA 程序中的漢字編碼問(wèn)題的方法往往很簡(jiǎn)單,但理解其背后的原因,定位問(wèn)題,還需要了解現(xiàn)有的漢字編碼和編碼轉(zhuǎn)換。
計(jì)算機(jī)要準(zhǔn)確的處理各種字符集文字,需要進(jìn)行字符編碼,以便計(jì)算機(jī)能夠識(shí)別和存儲(chǔ)各種文字。常見(jiàn)的字符編碼主要包括:ASCII編碼、GB**編碼、Unicode。下面LZ就簡(jiǎn)單地介紹下?。槭裁词呛?jiǎn)單介紹?因?yàn)長(zhǎng)Z在網(wǎng)上查找資料想去了解字符編碼時(shí),發(fā)現(xiàn)這個(gè)問(wèn)題比我想象的復(fù)雜太多了,所以LZ需要另起一篇詳細(xì)介紹,所以各位看客就簡(jiǎn)單看看吧?。。?/p>
ASCII,American Standard Code for Information Interchange,是基于拉丁字母的一套電腦編碼系統(tǒng),主要用于顯示現(xiàn)代英語(yǔ)和其他西歐語(yǔ)言。它是現(xiàn)今最通用的單字節(jié)編碼系統(tǒng)。
ASCII碼使用指定的7位或者8為二進(jìn)制數(shù)字組合表示128或者256種可能的字符。標(biāo)準(zhǔn)的ASCII編碼使用的是7(2^7 = 128)位二進(jìn)制數(shù)來(lái)表示所有的大小寫(xiě)字母、數(shù)字和標(biāo)點(diǎn)符號(hào)已經(jīng)一些特殊的控制字符,最前面的一位統(tǒng)一規(guī)定為0。其中0~31及127(共33個(gè))是控制字符或通信專用字符,32~126(共95個(gè))是字符(32是空格),其中48~57為0到9十個(gè)阿拉伯?dāng)?shù)字,65~90為26個(gè)大寫(xiě)英文字母,97~122號(hào)為26個(gè)小寫(xiě)英文字母,其余為一些標(biāo)點(diǎn)符號(hào)、運(yùn)算符號(hào)等。
ASCII最大的缺點(diǎn)就是顯示字符有限,他雖然解決了部分西歐語(yǔ)言的顯示問(wèn)題,但是對(duì)更多的其他語(yǔ)言他實(shí)在是無(wú)能為了。隨著計(jì)算機(jī)技術(shù)的發(fā)展,使用范圍越來(lái)越廣泛了,ASCII的缺陷越來(lái)越明顯了,其他國(guó)家和地區(qū)需要使用計(jì)算機(jī),必須要設(shè)計(jì)一套符合本國(guó)/本地區(qū)的編碼規(guī)則。例如為了顯示中文,我們就必須要設(shè)計(jì)一套編碼規(guī)則用于將漢字轉(zhuǎn)換為計(jì)算機(jī)可以接受的數(shù)字系統(tǒng)的數(shù)。
GB2312,用于漢字處理、漢字通信等系統(tǒng)之間的信息交換,通行于中國(guó)大陸。它的編碼規(guī)則是:小于127的字符的意義與原來(lái)相同,但兩個(gè)大于127的字符連在一起時(shí),就表示一個(gè)漢字,前面的一個(gè)字節(jié)(他稱之為高字節(jié))從0xA1用到 0xF7,后面一個(gè)字節(jié)(低字節(jié))從0xA1到0xFE,這樣我們就可以組合出大約7000多個(gè)簡(jiǎn)體漢字了。雖然GB2312收錄了這么多漢子,他所覆蓋的使用率可以達(dá)到99%,但是對(duì)于那些不常見(jiàn)的漢字,例如人名、地名、古漢語(yǔ),它就不能處理了,于是就有下面的GBK、GB 18030的出現(xiàn)。(點(diǎn)擊GB2312簡(jiǎn)體中文編碼表查看)。
GB18030,全稱:國(guó)家標(biāo)準(zhǔn)GB 18030-2005《信息技術(shù) 中文編碼字符集》,是我國(guó)計(jì)算機(jī)系統(tǒng)必須遵循的基礎(chǔ)性標(biāo)準(zhǔn)之一,GB18030有兩個(gè)版本:GB18030-2000和GB18030-2005。GB18030-2000是GBK的取代版本,它的主要特點(diǎn)是在GBK基礎(chǔ)上增加了CJK統(tǒng)一漢字?jǐn)U充A的漢字。
GB 18030主要有以下特點(diǎn):
GBK,漢字編碼標(biāo)準(zhǔn)之一,全稱《漢字內(nèi)碼擴(kuò)展規(guī)范》,它 向下與 GB 2312 編碼兼容,向上支持 ISO 10646.1 國(guó)際標(biāo)準(zhǔn),是前者向后者過(guò)渡過(guò)程中的一個(gè)承上啟下的標(biāo)準(zhǔn)。它的編碼范圍如下圖:
正如前面前面所提到的一樣,世界存在這么多國(guó)家,也存在著多種編碼風(fēng)格,像中文的GB232、GBK、GB18030,這樣亂搞一套,雖然在本地運(yùn)行沒(méi)有問(wèn)題,但是一旦出現(xiàn)在網(wǎng)絡(luò)上,由于互不兼容,訪問(wèn)則會(huì)出現(xiàn)亂碼。為了解決這個(gè)問(wèn)題,偉大的Unicode編碼騰空出世。
Unicode編碼的作用就是能夠使計(jì)算機(jī)實(shí)現(xiàn)夸平臺(tái)、跨語(yǔ)言的文本轉(zhuǎn)換和處理。它幾乎包含了世界上所有的符號(hào),并且每個(gè)符號(hào)都是獨(dú)一無(wú)二的。在它的編碼世界里,每一個(gè)數(shù)字代表一個(gè)符號(hào),每一個(gè)符號(hào)代表了一個(gè)數(shù)字,不存在二義性。
Unicode編碼又稱統(tǒng)一碼、萬(wàn)國(guó)碼、單一碼,它是業(yè)界的一種標(biāo)準(zhǔn),是為了解決傳統(tǒng)的字符編碼方案的局限而產(chǎn)生的,它為每種語(yǔ)言中的每個(gè)字符設(shè)定了統(tǒng)一并且唯一的二進(jìn)制編碼,以滿足跨語(yǔ)言、跨平臺(tái)進(jìn)行文本轉(zhuǎn)換、處理的要求。同時(shí)Unicode是字符集,它存在很多幾種實(shí)現(xiàn)方式如:UTF-8、UTF-16.
互聯(lián)網(wǎng)的普及,強(qiáng)烈要求出現(xiàn)一種統(tǒng)一的編碼方式。UTF-8就是在互聯(lián)網(wǎng)上使用最廣的一種unicode的實(shí)現(xiàn)方式。其他實(shí)現(xiàn)方式還包括UTF-16和UTF-32,不過(guò)在互聯(lián)網(wǎng)上基本不用。重復(fù)一遍:UTF-8是Unicode的實(shí)現(xiàn)方式之一。
UTF-8最大的一個(gè)特點(diǎn),就是它是一種變長(zhǎng)的編碼方式。它可以使用1~4個(gè)字節(jié)表示一個(gè)符號(hào),根據(jù)不同的符號(hào)而變化字節(jié)長(zhǎng)度。UTF-8的編碼規(guī)則很簡(jiǎn)單,只有兩條:1)對(duì)于單字節(jié)的符號(hào),字節(jié)的第一位設(shè)為0,后面7位為這個(gè)符號(hào)的unicode碼。因此對(duì)于英語(yǔ)字母,UTF-8編碼和ASCII碼是相同的。2)對(duì)于n字節(jié)的符號(hào)(n>1),第一個(gè)字節(jié)的前n位都設(shè)為1,第n+1位設(shè)為0,后面字節(jié)的前兩位一律設(shè)為10。剩下的沒(méi)有提及的二進(jìn)制位,全部為這個(gè)符號(hào)的unicode碼。
此篇博文只是開(kāi)篇之作,啟下之用, 對(duì)字符集的介紹也只是簡(jiǎn)簡(jiǎn)單單,沒(méi)有太多的描述,因?yàn)長(zhǎng)Z在查字符集的資料過(guò)程中發(fā)現(xiàn)字符集真的是太復(fù)雜了,LZ有點(diǎn)兒駕馭不了,需要仔細(xì)研究,然后寫(xiě)一篇較為詳細(xì)的博文!各位敬請(qǐng)期待??!
參考文獻(xiàn):
字符集和字符編碼:http://www.cnblogs.com/skynet/archive/2011/05/03/2035105.html百度百科 ASCII:http://baike.baidu.com/view/15482.htm
百度百科:GB2312:http://baike.baidu.com/view/443268.htm?fromtitle=GB2312&fromid=483170&type=syn
百度百科:GB18030:http://baike.baidu.com/view/889058.htm
百度百科:GBK:http://baike.baidu.com/view/931619.htm?fromtitle=GBK&fromid=481954&type=search
百度百科:Unicode:http://baike.baidu.com/view/40801.htm
百度百科:UTF-8:http://baike.baidu.com/view/25412.htm
更多建議: