亂碼問(wèn)題好像跟我們中國程序員特別有緣,一直困擾著(zhù)我們,從開(kāi)始的JSP亂碼問(wèn)題,STRUTS亂碼問(wèn)題,到現在的AJAX亂碼問(wèn)題,無(wú)一不是搞得許多程序員焦頭爛額的,整天罵XXX產(chǎn)品對中文支持不了,UTF-8無(wú)法使用中文啊什么的,其實(shí)這里面被罵的產(chǎn)品中其實(shí)99%以上是對中文支持非常好的,而出現亂碼的原因只是因為自身對國際化支持以及文件編碼等信息的認識不知造成的。要知道一個(gè)產(chǎn)品那么流行,怎么可能對中文支持不了呢,下面就開(kāi)始一一幫大家解決這些問(wèn)題。
1、編碼
--想要解決好中文問(wèn)題,對編碼肯定是不能一概不懂了,編碼是解決中文亂碼問(wèn)題的根本。
編碼比較常用的有:UTF-8,GBK,GB2312,ISO-8859-1,除了iso-8859-1之外的其它三個(gè)編碼都能很好的支持中文,但它們都兼容ISO-8859-1的編碼(就是說(shuō)無(wú)論編碼怎么改變,只要是ISO-8859-1中的字符,永遠不會(huì )出現亂碼)。
這四種編碼中,GB2312是中國規定的漢字編碼,也可以說(shuō)是簡(jiǎn)體中文的字符集編碼;GBK 是GB2312的擴展,除了兼容GB2312外,它還能顯示繁體中文,還有日文的假名;而UTF-8雖然也支持中文,但卻與GB碼不兼容(編碼值不同)。UTF-8使用的是可變長(cháng)的UNICODE編碼,編碼可能是1位16進(jìn)制(即ISO-8859-1中的字符,其編碼也是相同的)也有可能是2位或3位的16進(jìn)制。UTF-8的優(yōu)點(diǎn)是:1、與CPU字節順序無(wú)關(guān), 可以在不同平臺之間交流。2、容錯能力高, 任何一個(gè)字節損壞后, 最多只會(huì )導致一個(gè)編碼碼位損失, 不會(huì )鏈鎖錯誤(如GB碼錯一個(gè)字節就會(huì )整行亂碼),所以在國際化處理中基本都是建議使用UTF-8作為編碼。
2、文件的編碼
--雖然說(shuō)只要設置了正確的編碼就可以使字符正確顯示了,但如果忽略了文件保存時(shí)的編碼的話(huà),那可是會(huì )讓你走進(jìn)迷霧中的。
文件編碼最常使用的有兩種:ANSI和UTF-8,光看名字估計你都可以猜到了,ANSI就是我們保存文件時(shí)使用的默認編碼,而UTF-8則需自己設置。對于編碼的改變,我使用的工具是NOTEPAD和ECLIPSE,NOTEPAD使用最簡(jiǎn)單,只要打開(kāi)文件后在另存為中選擇相應的編碼就行了,而且它對編碼的支持非常好;而在ECLIPSE中,只要稍微設置一下就行了,打開(kāi)首選項,然后選擇:常規->內容類(lèi)型(ContentType),在右邊選中你想改變保存編碼的文件類(lèi)型,然后在下方的缺省編碼中改變其值,最后點(diǎn)擊更新(UPDATE)按鈕即可。

而在其它的編輯器中,默認保存的內容都是GB2312或者GBK(NOTEPAD中對應ANSI).而根據前面所說(shuō)的UTF-8和GBK,GB2312等的編碼值是不同的這一點(diǎn),可以知道,如果文件使用了UTF-8,那么字符編碼就必須使用UTF-8,否則編碼值的不同就可能造成亂碼。而這也就是為什么那么多的人使用了UTF-8編碼后還會(huì )產(chǎn)生亂碼的根本原因。(JS和JSP都是這個(gè)道理)
3、JSP,STRUTS等的中文亂碼解決方案
其實(shí)解決的方法只有一個(gè):
request.setCharacterEncoding(encoding); 方法只有一種,但處理方式就多種多樣了,初學(xué)者會(huì )在JSP頁(yè)面上直接使用,而有經(jīng)驗的程序員會(huì )使用過(guò)濾器。而現在所要說(shuō)的方法也是過(guò)濾器。這里以統一使用UTF-8作為編碼作為例子說(shuō)明。具體過(guò)程就不多說(shuō)了,網(wǎng)上有很多教程。偷懶一點(diǎn)的,到TOMCAT中復制就行了。在TOMCAT的目錄下的webapps\jsp-examples\WEB-INF\classes\filters\找到SetCharacterEncodingFilter.java這個(gè)類(lèi),放到你的程序中并配置好映射路徑。配置好后基本上你的亂碼問(wèn)題就解決了。但要映射路徑中需要注意的就是不能使用 ‘*‘
<filter-mapping>
<filter-name>Set Character Encoding</filter-name>
<servlet-name>*</servlet-name>
</filter-mapping> 像上面這樣配置的話(huà)(可能也是網(wǎng)上大多教程的做法,想當年也是害苦了我),可能你只有JSP的亂碼解決了,要解決STRUTS的亂碼需要映射 *.do 或者 servletActionName。然后在初始化參數中設置encoding的值就行了。
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param> 當然,最重要的是要記得根據前面所說(shuō)的方法,改變你所使用的編輯器保存文件的編碼要與使用的字符編碼一致。
而在JSP內容中,還是使用如網(wǎng)上教程所說(shuō)的那種技倆,在所有頁(yè)面的頁(yè)首加入:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%> 至此,相信JSP,ACTION都不太可能出現亂碼了。
4、資源文件的亂碼解決方案
資源文件誰(shuí)都知道是國際化支持不可或缺的一部分,如果資源文件都出現亂碼了那還了得?其實(shí)資源文件的亂碼是很好解決的,其原因也是因為使用了UTF-8做為JSP編碼后,沒(méi)有相應地改變資源文件的文件編碼造成的,所以只要對資源文件保存的編碼進(jìn)行更正后,亂碼問(wèn)題也就解決了。當然,你的中文要使用native2ascii 命令進(jìn)行正確的轉換。
5、調用JS時(shí),JS內容亂碼的解決方案。
其實(shí)JS的亂碼還是跟文件的編碼有關(guān)系的,如果JS中有中文的話(huà),那JS文件保存的編碼就必須跟調用此JS的頁(yè)面編碼相同,否則,你的所有中文都要從JSP頁(yè)面傳給JS才會(huì )顯示正常??梢钥闯鰧τ谡{用JS出現的亂碼是最容易解決的(也是建立在前面的辛苦之下的)。
6、AJAX提交數據亂碼,返回數據亂碼的解決方案
隨著(zhù)AJAX的流行,亂碼問(wèn)題也開(kāi)始困擾著(zhù)許多剛開(kāi)始使用它的程序員,幸好我之前對JSP亂碼有過(guò)一點(diǎn)研究,在遇到AJAX后,并沒(méi)有給我帶來(lái)多大的困擾,在此將我的一些心得共享給大家。
萬(wàn)變不離其宗,AJAX的亂碼問(wèn)題自然跟編碼有關(guān)了,其實(shí)很多人跟我一樣想到了對文件編碼進(jìn)行設置,并且在接數據時(shí)設置了requet的編碼,在返回的數據時(shí)設置了response的編碼一切都以為會(huì )很順利,可是這一切都是徒勞無(wú)功的,討厭的亂碼再一次出現在你眼前。在你試了N多種方法,包括JS自身的escape,unescape方法后,你發(fā)現亂碼仍然猖狂地出現在屏幕上。
其實(shí)在試過(guò)這N多方法后,很多人都沒(méi)發(fā)現,解決的方法其實(shí)很簡(jiǎn)單,而且其答案就在我們之前處理的JSP亂碼之中。讓我們先看一下AJAX的經(jīng)典請求代碼
xmlhttp.open( "post", url, async );
xmlhttp.setRequestHeader( "Content-Type", "text/html" );
xmlhttp.send( params );
通過(guò)前面的說(shuō)明,不知道你現在看出端倪了沒(méi)有。不知道是受了網(wǎng)上教程的影響還是其它方面影響,setRequestHeader并是萬(wàn)年不變的,也沒(méi)人想過(guò)去改它,而問(wèn)題就正好出在這個(gè)地方?;叵胍粋€(gè)JSP頁(yè)面內容的編碼設置,其中有這么一節:contentType="text/html; charset=UTF-8"
現在知道問(wèn)題了吧,所以我們要把第二句代碼改為:xmlhttp.setRequestHeader( "Content-Type", "text/html;charset=UTF-8" );
最后別忘了在返回數據時(shí)也設置上:response.setContentType( "text/xml" );
response.setCharacterEncoding( "UTF-8" );
是不是很簡(jiǎn)單,一點(diǎn)都不麻煩呢?
如果要問(wèn)為什么的話(huà),其實(shí)我們可以把xmlhttp看成是一個(gè)臨時(shí)頁(yè)面,它由瀏覽器動(dòng)態(tài)生成,主要作用是在后臺獲得請求的數據(可以看成是一個(gè)高級的iframe)。所以對于普通頁(yè)面設置的編碼,對它也要同樣設置。而在servlet中返回數據為什么要設置contentType和encoding其道理也是一樣的。眾所周知,jsp的最后形態(tài)就是servlet,而jsp頁(yè)首設置的那個(gè)內容其實(shí)也就是讓生成的servlet中生成這么兩句話(huà):
response.setContentType( "text/html" );
response.setCharacterEncoding( "UTF-8" );
而pageEncoding則是跟jvm說(shuō)明了這個(gè)頁(yè)面的內容要使用什么編碼保存(這跟之后生成的CLASS有關(guān)系)。所以在servlet設置response的編碼也是理所當然的了。
一口氣把自己一年以來(lái)遇到的亂碼問(wèn)題和解決的方案寫(xiě)出來(lái)了,希望對你有所幫助。