首先看一段亂碼的程序: protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //0設(shè)置編碼 request.setCharacterEncoding("UTF-8"); String username=request.getParameter("username"); String password=request.getParameter("userPwd"); System.out.println("處理之前:"+username+":"+password); //此時(shí)輸出的結(jié)果:處理之前:è????????:aa1234bb---也就是說(shuō)中文字符本身的編碼還是不對(duì)。 //做如下處理: username = new String(username.getBytes("ISO8859-1"),"UTF-8"); System.out.println("處理之后:"+username+":"+password); response.setContentType("text/html;charset=UTF-8"); ServletOutputStream out=response.getOutputStream(); out.println(username); out.println(password); } 亂碼原因的分析: get請(qǐng)求的原理圖: 1.數(shù)據(jù)解析編碼:指的是html頁(yè)面form表當(dāng)數(shù)據(jù)提交時(shí)候的編碼方式,這個(gè)編碼方式和頁(yè)面編碼是統(tǒng)一的,這里設(shè)置為UTF-8 2.GET請(qǐng)求的的請(qǐng)求數(shù)據(jù),并不在請(qǐng)求體體中,而是在請(qǐng)求行中的?之后。而整個(gè)請(qǐng)求數(shù)據(jù),包括請(qǐng)求行,請(qǐng)求頭,請(qǐng)求體都會(huì)通過(guò)http協(xié)議發(fā)送到服務(wù)端去處理。(HTTP協(xié)議時(shí)不支持中文的,默認(rèn)編碼:ISO8859-1) 對(duì)比post請(qǐng)求,post請(qǐng)求的的請(qǐng)求數(shù)據(jù)都包含在請(qǐng)求體中,當(dāng)發(fā)送了了服務(wù)端的時(shí)候,通過(guò)設(shè)置request.setCharacterEncoding("UTF-8"),就能夠使得數(shù)據(jù)傳輸?shù)椒?wù)端的時(shí)候,能夠?qū)⑵浣馕龀蓇tf-8的數(shù)據(jù)。 但是,這樣的設(shè)置編碼的操作對(duì)請(qǐng)求行中的數(shù)據(jù)缺失無(wú)效的。 3.前面說(shuō)了數(shù)據(jù)時(shí)通過(guò)http協(xié)議的方式發(fā)送到服務(wù)端,而請(qǐng)求行的信息(原始狀態(tài)下是UTF-8編碼)經(jīng)過(guò)http協(xié)議進(jìn)行傳輸?shù)臅r(shí)候,http協(xié)議對(duì)其進(jìn)行了默認(rèn)編碼的編碼操作。并發(fā)送到了服務(wù)端,而服務(wù)端類似post請(qǐng)求的處理方式,對(duì)其有沒有作用。 那么,服務(wù)段應(yīng)該如何對(duì)這樣的亂碼,就行解碼,讓其還原成UTF-8編碼呢。實(shí)際上就是還原成原始數(shù)據(jù)的編碼? (亂碼產(chǎn)生的核心本質(zhì):源編碼和讀取顯示的編碼不一致) 思路:找到源編碼的二進(jìn)制,然后重新用UTF-8進(jìn)行解碼就可以了。 4.解決辦法: 服務(wù)端:String username=request.getParamter("username");----這是獲得的ISO8859-1編碼的亂碼數(shù)據(jù) 解碼: username.getBytes("ISO8859-1");-----這樣就獲得了原始數(shù)據(jù)。 而原始數(shù)據(jù)就是按照UTF-8編碼的,那么此時(shí),只需要將其變成UTF-8的字符串?dāng)?shù)據(jù)就ok new String(username.getBytes("ISO8859-1,"UTF-8"")); 最終表現(xiàn)在上面的程序中,值處理之前,是亂碼的,通過(guò)解碼在還原的操作,中文則不再亂碼。仍然存在的疑惑: 1. response.setContentType("text/html;charset=UTF-8"); 如果沒有手動(dòng)解碼的代碼username.getBytes("ISO8859-1"); 通過(guò)上述方式設(shè)置response編碼,將其發(fā)送到瀏覽器,沒有出現(xiàn)亂碼。 這種情形是合理的嗎?是不是上述操作的底層也是用過(guò)來(lái)類似 username.getBytes("ISO8859-1") 這樣的解碼方式?(可以這么理解) 2.如果是post請(qǐng)求的時(shí)候,請(qǐng)求內(nèi)容在請(qǐng)求體中,不也要通過(guò)http協(xié)議對(duì)其進(jìn)行編碼嗎?為什么數(shù)據(jù)發(fā)送到服務(wù)端,就直接可以通過(guò) request.setCharcterEncoding(UTF-8)對(duì)數(shù)據(jù)進(jìn)行解碼?(視頻里面提到流的處理方式) 這里面,request.setCharacterEncoding(UTF-8)值能請(qǐng)求體中的流進(jìn)行處理。 那么這個(gè)還有一個(gè)問題就是, response.setContentType("text/html;charset=UTF-8"); ServletOutputStream out=response.getOutputStream(); out.println(username); out.println(password); 做了這樣的操作以后,即使沒有手動(dòng)解碼,在服務(wù)端通過(guò)上述流操作,將數(shù)據(jù)輸出到瀏覽器中,沒有出現(xiàn)亂碼。 那么對(duì)于get請(qǐng)求,手動(dòng)解碼的意義是什么呢。后來(lái)明白了,因?yàn)榇蠖鄶?shù)情況下,還是要將數(shù)據(jù)信息存儲(chǔ)到數(shù)據(jù)庫(kù)中個(gè), 存儲(chǔ)到數(shù)據(jù)庫(kù)的操作,可不是流的操作, 那么這個(gè)時(shí)候,如果這屆存儲(chǔ)到數(shù)據(jù)庫(kù)的情況下,就會(huì)亂碼的。所以通過(guò)手動(dòng)解碼的方式的意義還是大大的。 當(dāng)然,一般不用字節(jié)流來(lái)處理文本數(shù)據(jù),上述代碼,改成response.getWriter的方式處理就ok。 |
|