【Java】中文亂碼不再亂

     小編總結了一下一些中文亂碼的心得,總結一下積累。(最近更新2017年5月9日)

【爲什麼】

      在頁面上輸入信息,通過表單等打包提交成request請求發給服務器,jsp在運行時總是被編譯成servlet,這期間也會有字符的編譯,最終將數據插入數據庫中,數據庫的字符集等等,這期間的各種字符編碼的轉換傳輸等等都會造成亂碼。一個J2EE系統的各個組成部分都有各自的字符集編碼,如果不做字符集統一,必然會出現亂碼。

【解決方案】

       UTF-8無疑是最好的統一選擇,UTF-8編碼兼容所有語言(具體的編碼比較見文尾),唯一比較麻煩的就是需要在數據從輸入到進數據庫這一系列操作的所有出入管你口都用UTF-8來統一。如下:

1.需要在項目開發和編譯時指定字符集UTF-8。Eclipse就直接設置整個項目的屬性即可。如下圖:


2.在JSP的頭部進行聲明:

<%@ pagelanguage="java"contentType="text/html;charset=UTF-8"pageEncoding="UTF-8"%>

3.也可以使用過濾器,所有請求都要經過servlet控制分配器,在servlet的filter設置統一。

       詳見博客:http://blog.csdn.net/u013036274/article/details/52592818

4.設定數據庫連接方式爲UTF-8。以mysql連接爲例,在連接mysql配置url時:

<?xmlversion="1.0" encoding="UTF-8"?>
<config>
<db-info>
<driver-name>com.mysql.jdbc.Driver</driver-name>       
<url>jdbc:mysql://localhost:3306/drp?characterEncoding=UTF-8</url>
<user-name>root</user-name>
<password>123456</password>
</db-info>
</config>

5.數據庫設置爲UTF-8,如下圖:


6.JSP與頁面參數之間的亂碼轉換

Request.setCharacterEncoding("UTF-8");//從請求中獲取參數出現亂碼
response.setContentType("text/html;charset=GBK");//將變量輸出到頁面時出現亂碼

    這種情況綜合起來還是直接使用過濾器比較合適。

7.Filter設置字符集對get提交方式並不起作用,所以還有一種方式,是配置服務器。一Tomcat爲例:Tomcat的配置文件中:.me_tcat/conf/server.xml,如下圖:


打開進行如下修改:


8.對中文采用Java.net.URLEncoder.encode()進行編碼

 URLEncoder.encode("某中文", "GB18030")

9.其他 

       上面提到的方法應該能解決大部分亂碼問題,如果在其他地方還出現亂碼,可能需要手動修改代碼。

String test=newString(name.getBytes("gbk"),"utf-8");

10.瀏覽器中文亂碼

      最近小編做項目遇到了這樣一個問題:通過上文的方法,可以保證谷歌、火狐等瀏覽器都沒問題,但是IE卻依然亂碼,這是因爲IE和火狐對URL的處理不同,瀏覽器在傳輸URI時得對URL進行編碼,IE默認是以UTF_8來傳輸的,Firefox是GBK來編碼,如果不對中文參數進行處理,中文字符經過各個瀏覽器以各自的方式傳輸到服務器後就出現了各種編碼方式,而服務器卻只能以一種編碼方式來對接收到得URL進行解碼,這樣的話和服務器使用的編碼方式一致的瀏覽器在傳中文參數時沒問題,不一致的就會有問題。解決方法也很簡單,上文介紹中少了一個地方,就是在參數傳遞之前。我們可以再參數傳遞之前就進行編碼,後臺獲取參數時再解碼即可,並且這種方式可以很好的處理瀏覽器兼容性問題,這樣的話下面的那一段補充液沒用了,因爲我們根本就不需要知道原來是什麼編碼。如下:

js代碼:

	var url =encodeURI("transport/viewTransitList.do?searchOption="
			+ searchOption + "&searchCondition="
			+ searchCondition);

Controller代碼:

		String searchCondition=request.getParameter("searchCondition");
		try {			
			 searchCondition = java.net.URLDecoder.decode(searchCondition, "UTF-8");// 解碼
			searchCondition = new String(searchCondition.getBytes("iso-8859-1"), "utf-8");
		
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}	

補充:解決Java亂碼問題的關鍵在於在字節與字符的轉換過程中,你必須知道原來字節或轉換後的字節的編碼方式,轉換時採用的編碼必須與這個編碼方式保持一致。但是如何獲取字符串的編碼格式,實驗了幾個網上的方案,無果。待續。。。。

【幾種編碼格式的介紹】----(摘自博客見文尾鏈接)

       當中國人們得到計算機時,已經沒有可以利用的字節狀態來表示漢字,況且有6000多個常用漢字需要保存,於是想到把那些ASCII碼中127號之後的奇異符號們直接取消掉,規定:一個小於127的字符的意義與原來相同,但兩個大於127的字符連在一起時,就表示一個漢字,前面的一個字節(稱之爲高字節)從0xA1用到0xF7,後面一個字節(低字節)從0xA1到0xFE,這樣我們就可以組合出大約7000多個簡體漢字了。在這些編碼裏,我們還把數學符號、羅馬希臘的字母、日文的假名們都編進去了,連在ASCII 裏本來就有的數字、標點、字母都統統重新編了兩個字節長的編碼,這就是常說的"全角"字符,而原來在127號以下的那些就叫"半角"字符了。這種漢字方案叫做"GB2312"。GB2312 是對 ASCII 的中文擴展。兼容ASCII。

       但是中國的漢字太多了,我們很快就就發現有許多人的人名沒有辦法在這裏打出來,不得不繼續把GB2312沒有用到的碼位找出來用上。後來還是不夠用,於是乾脆不再要求低字節一定是127號之後的內碼,只要第一個字節是大於127就固定表示這是一個漢字的開始,不管後面跟的是不是擴展字符集裏的內容。結果擴展之後的編碼方案被稱爲“GBK” 標準,GBK 包括了 GB2312 的所有內容,同時又增加了近20000個新的漢字(包括繁體字)和符號。

       後來少數民族也要用電腦了,於是我們再擴展,又加了幾千個新的少數民族的字,GBK擴成了 GB18030。從此之後,中華民族的文化就可以在計算機時代中傳承了。

       中國的程序員們看到這一系列漢字編碼的標準是好的,於是通稱他們叫做"DBCS"(Double ByteCharecter Set雙字節字符集)。在DBCS系列標準裏,最大的特點是兩字節長的漢字字符和一字節長的英文字符並存於同一套編碼方案裏,因此他們寫的程序爲了支持中文處理,必須要注意字串裏的每一個字節的值,如果這個值是大於127的,那麼就認爲一個雙字節字符集裏的字符出現了。在這種情況下,"一個漢字算兩個英文字符!"。然而,在Unicode環境下卻並非總是如此。

       在Unicode裏,所有的字符被一視同仁。漢字不再使用“兩個擴展ASCII”,而是使用“1個Unicode”,注意,現在的漢字是“一個字符”了,於是,拆字、統計字數這些問題也就自然而然的解決了。

       但是,這個世界不是理想的,不可能在一夜之間所有的系統都使用Unicode來處理字符,所以Unicode在誕生之日,就必須考慮一個嚴峻的問題:和ASCII字符集之間的不兼容問題。

       我們知道,ASCII字符是單個字節的,比如“A”的ASCII是65。而Unicode是雙字節的,比如“A”的Unicode是0065,這就造成了一個非常大的問題:以前處理ASCII的那套機制不能被用來處理Unicode了。

       另一個更加嚴重的問題是,C語言使用'\0'作爲字符串結尾,而Unicode裏恰恰有很多字符都有一個字節爲0,這樣一來,C語言的字符串函數將無法正常處理Unicode,除非把世界上所有用C寫的程序以及他們所用的函數庫全部換掉。

       於是,比Unicode更偉大的東東誕生了,之所以說它更偉大是因爲它讓Unicode不再存在於紙上,而是真實的存在於我們大家的電腦中。那就是:UTF。

       UTF= UCS TransformationFormat,即UCS轉換(傳輸)格式。它是將Unicode編碼規則和計算機的實際編碼對應起來的一個規則。現在流行的UTF有2種:UTF-8和UTF-16。這兩種都是Unicode的編碼實現。

下面兩篇博客對這方面介紹的生動風趣,有興趣可以看一下。

http://blog.csdn.net/guanfengliang1988/article/details/50440197

http://blog.csdn.net/ldanduo/article/details/8203532/

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章