引言: 在Restful類的服務設計中,經常會碰到需要在URL地址中使用中文作為的參數的情況,這種情況下,一般都需要正確的設置和編碼中文字符信息。亂碼問題就此產生了,該如何解決呢?且聽本文詳細道來。
1. 問題的引出
在Restful的服務設計中,查詢某些信息的時候,一般的URL地址設計為: get /basic/service? keyword=歷史 , 之類的URL地址。 但是,在實際的開發和使用中,確是有亂碼情況的發生,在后台的讀取keyword信息為亂碼,無法正確讀取。
2. 亂碼是如何產生的?
5. 后台如何正確解析中文字符信息?
進入后台的信息,在經過二次encodeURI()之后,直接讀取是無法后去正確的信息的。 需要繼續如下處理:
- URLDecoder.decode("chinese string","UTF-8")
URLDecoder的decode(String str,String ecn)方法有兩個參數,第一個參數為待解碼的字符串,第二個參數為解碼時的對應編碼。
6. encodeURI, encodeURIComponent, escape
6.1 escape()函數
escape() 函數可對字符串進行編碼,這樣就可以在所有的計算機上讀取該字符串。
返回值:已編碼的 string 的副本。其中某些字符被替換成了十六進制的轉義序列。
說明 :該方法不會對 ASCII 字母和數字進行編碼,也不會對下面這些 ASCII 標點符號進行編碼: - _ . ! ~ * ' ( ) 。其他所有的字符都會被轉義序列替換。所有的空格符、標點符號、特殊字符以及其他非ASCII字符都將被轉化成%xx格式的字符編碼(xx等於該字符在字符集表里面的編碼的16進制數字)。比如,空格符對應的編碼是%20。不會被此方法編碼的字符: @ * / +
6.2 encodeURI() 方法
把URI字符串采用UTF-8編碼格式轉化成escape格式的字符串。不會被此方法編碼的字符:! @ # $& * ( ) = : / ; ? + '
6.3 encodeURIComponent() 方法
把URI字符串采用UTF-8編碼格式轉化成escape格式的字符串。與encodeURI()相比,這個方法將對更多的字符進行編碼,比如 / 等字符。所以如果字符串里面包含了URI的幾個部分的話,不能用這個方法來進行編碼,否則 / 字符被編碼之后URL將顯示錯誤。
不會被此方法編碼的字符:! * ( ) '
因此,對於中文字符串來說,如果不希望把字符串編碼格式轉化成UTF-8格式的(比如原頁面和目標頁面的charset是一致的時候),只需要使用escape。如果你的頁面是GB2312或者其他的編碼,而接受參數的頁面是UTF-8編碼的,就要采用encodeURI或者encodeURIComponent。
7. 另一種處理URL的中文亂碼方案
請求端的中字符有encodeURI進行一次轉碼,如:
var url="/ajax?name="+encodeURI(name);
服務器端代碼:
name=new String(name.getBytes("iso8859-1"),"UTF-8");
注: name為獲得的字符串,iso8859-1為項目的默認字符編碼,如果為中文編碼gbk,gb2312等則不用這一步進行處理.
分析: 經過程序驗證,結果可行的。 由此可知,瀏覽器本身默認的編碼方式是iso8859-1的方式,即使使用了encodeURI進行了utf-8編碼處理,主要的字符串內容,比如ascii字符和可見字符都還是基於iso8859-1瀏覽器自身的字符。原因就是這些字符在編碼上和UTF-8字符串是重合的。而encodeURI之類的轉義函數主要解決,特殊字符%,/之類的字符的轉義問題。
javascript中encodeURI和decodeURI方法
一、基本概念
encodeURI和decodeURI是成對來使用的,因為瀏覽器的地址欄有中文字符的話,可以會出現不可預期的錯誤,所以可以encodeURI把非英文字符轉化為英文編碼,decodeURI可以用來把字符還原回來。encodeURI方法不會對下列字符進行編碼:":"、"/"、";" 和 "?",encodeURIComponent方法可以對這些字符進行編碼。
decodeURI()方法相當於java.net.URLDecoder.decode(URIString, "UTF-8");
encodeURI()方法相當於java.net.URLEncoder.encode(URIString, "UTF-8");
二、例子
<script type="text/javascript">
var uriStr = "http://www.baidu.com?name=張三&num=001 zs";
var uriec = encodeURI(uriStr);
document.write("編碼后的" + uriec);
var uridc = decodeURI(uriec);
document.write("解碼后的" + uridc);
</script>
編碼后的http://www.baidu.com?name=%E5%BC%A0%E4%B8%89&num=001%20zs
解碼后的http://www.baidu.com?name=張三&num=001 zs
java jdk中說明:java.net.URLEncoder.encode(URIString, "UTF-8");
HTML 格式編碼的實用工具類。該類包含了將 String 轉換為 application/x-www-form-urlencoded MIME 格式的靜態方法。有關 HTML 格式編碼的更多信息,請參閱 HTML 規范。
對 String 編碼時,使用以下規則:
- 字母數字字符 "
a" 到 "z"、"A" 到 "Z" 和 "0" 到 "9" 保持不變。 - 特殊字符 "
."、"-"、"*" 和 "_" 保持不變。 - 空格字符 "
" 轉換為一個加號 "+"。 - 所有其他字符都是不安全的,因此首先使用一些編碼機制將它們轉換為一個或多個字節。然后每個字節用一個包含 3 個字符的字符串 "
%xy" 表示,其中 xy 為該字節的兩位十六進制表示形式。推薦的編碼機制是 UTF-8。但是,出於兼容性考慮,如果未指定一種編碼,則使用相應平台的默認編碼。
例如,使用 UTF-8 編碼機制,字符串 "The string ü@foo-bar" 將轉換為 "The+string+%C3%BC%40foo-bar",因為在 UTF-8 中,字符 ü 編碼為兩個字節,C3 (十六進制)和 BC (十六進制),字符 @ 編碼為一個字節 40 (十六進制)。
encode
public static String encode(String s, String enc) throws UnsupportedEncodingException
-
使用指定的編碼機制將字符串轉換為
application/x-www-form-urlencoded格式。該方法使用提供的編碼機制獲取不安全字符的字節。注:World Wide Web Consortium Recommendation 聲明應使用 UTF-8。如果不使用該編碼,可能造成不兼容性。
-
- 參數:
-
s- 要轉換的String。 -
enc- 所支持的 字符編碼名稱。 - 返回:
-
已轉換的
String。 - 拋出:
-
UnsupportedEncodingException- 如果不支持指定的編碼
jdk中說明:java.net.URLDecoder.decode(URIString, "UTF-8");
HTML 格式解碼的實用工具類。該類包含了將 String 從 application/x-www-form-urlencoded MIME 格式解碼的靜態方法。
該轉換過程正好與 URLEncoder 類使用的過程相反。假定已編碼的字符串中的所有字符為下列之一:"a" 到 "z"、"A" 到 "Z"、"0" 到 "9" 和 "-"、"_"、"." 以及 "*"。允許有 "%" 字符,但是將它解釋為特殊轉義序列的開始。
轉換中使用以下規則:
- 字母數字字符 "
a" 到 "z"、"A" 到 "Z" 和 "0" 到 "9" 保持不變。 - 特殊字符 "
."、"-"、"*" 和 "_" 保持不變。 - 加號 "
+" 轉換為空格字符 ""。 - 將把 "
%xy" 格式序列視為一個字節,其中 xy 為 8 位的兩位十六進制表示形式。然后,所有連續包含一個或多個這些字節序列的子字符串,將被其編碼可生成這些連續字節的字符所代替。可以指定對這些字符進行解碼的編碼機制,或者如果未指定的話,則使用平台的默認編碼機制。
該解碼器處理非法字符串有兩種可能的方法。一種方法是不管該非法字符,另一種方法是拋出 IllegalArgumentException 異常。解碼器具體采用哪種方法取決於實現。
decode
public static String decode(String s, String enc) throws UnsupportedEncodingException
-
使用指定的編碼機制對
application/x-www-form-urlencoded字符串解碼。給定的編碼用於確定任何 "%xy" 格式的連續序列表示的字符。注:World Wide Web Consortium Recommendation 聲明應使用 UTF-8。如果不使用該編碼,可能造成不兼容性。
-
- 參數:
-
s- 要解碼的String -
enc- 所支持的 字符編碼的名稱。 - 返回:
-
新解碼的
String - 拋出:
-
UnsupportedEncodingException- 如果需要參考字符編碼,而指定的字符編碼不被支持
對於Post請求,只需在Servlet或者jsp中寫入如下代碼就可以把解決從表單中傳入的中文亂碼問題
request.setCharacterEncoding("utf-8");
而對於Get請求,因為請求參數會被附加到地址欄的URL之后,所以不能用上面的處理方法。應該這樣:
String str=request.getQueryString();
//使用URLDecoder解碼字符串
String str1=java.net.URLDecoder.decode(str,"utf-8");
String[] paraStrings=str1.split("&");
//paraStrings[0]就是第一個參數,依次類推...
for(String paraString : paraStrings)
{
String[] nameValue=paraString.split("=");
//nameValue[0]就是表單的name,nameValue[1]就是表單name對應的值
}
還有一種方法就是獲取請求參數之后對請求參數值重新編碼,也就是先將其轉換成字節數組,再將字節數組重新解碼成字符串。
String str=request.getParameter("name");
byte[] bytes=str.getBytes("ISO-8859-1");
String name=new String(bytes,"utf-8");
