1. 程式人生 > >中文亂碼在java中URLEncoder.encode方法要呼叫兩次解決 (原理)

中文亂碼在java中URLEncoder.encode方法要呼叫兩次解決 (原理)

一、場景: 1、我在客戶端要通過get方式呼叫伺服器端的url,將中文引數做utf-8編碼,需要在js中兩次的進行編碼,伺服器端才能用decode方法一次獲取。 例如:
  1. var xing=encodeURIComponent(encodeURIComponent(xing));  

2、如果我在客戶端用java輸出漢字作為引數,並且用http協議,也是需要兩次才能在伺服器端正常的一次decode
  1. xing=URLEncoder.encode(xing,"UTF-8");  
  2. xing=URLEncoder.encode(xing,"UTF-8");  

伺服器端只需要一次decode xing=URLDecoder.decode(xing, "UTF-8");

二、原理: 因為在jsp中對中文進行了編碼的時候用的是UTF-8的編碼方式,而在servlet中呼叫request.getParameter();方法的時候使用伺服器指定的編碼格式自動解碼一次,所以前臺編碼一次後臺解碼一次而解碼和編碼的方式不用所以造成了亂碼的出現,

這就類似於以下程式碼:

            String name
=java.net.URLEncoder.encode("測試", "UTF-8");
System.out.println(name);
System.out.println(java.net.URLDecoder.decode(name,
"ISO-8859-1"));
編碼後的是%E6%B5%8B%E8%AF%95。。
而用ISO-8859-1解碼後的是???è?。。

但是如果呼叫的是 System.out.println(java.net.URLDecoder.decode(name, "UTF-8"));
則結果是列印“測試”。

這就印證了 之前為什麼我在servlet中呼叫java.net.URLDecoder.decode(request.getParameter("name"), "UTF-8")方法和呼叫java.net.URLDecoder.decode(request.getQueryString(), "UTF-8")所得到的結果是不一樣的,就是由於在request.getParameter("name")之前會自動做一次解碼的工作,而且是預設的ISO-8859-1。

所以,在使用java.net.URLEncoder.decode()和java.net.URLDecoder.decode(),的時候需要在前端頁面中使用兩次java.net.URLDecoder.decode()方法。

使用兩次編碼的過程相當於如下程式碼:
複製程式碼
String name=java.net.URLEncoder.encode("測試", "UTF-8");
System.out.println(name);
name
=java.net.URLEncoder.encode(name,"UTF-8");
System.out.println(name);
name
=java.net.URLDecoder.decode(name, "UTF-8");
System.out.println(name);
System.out.println(java.net.URLDecoder.decode(name,
"UTF-8")); 複製程式碼
輸出為:

            %E6%B5%8B%E8%AF%95
            %25E6%25B5%258B%25E8%25AF%2595
            %E6%B5%8B%E8%AF%95
            測試

第一次編碼後將漢字編碼為%和字母數字的格式,而第二次編碼的時候是對%字母數字進行編碼,雖然解碼的時候使用的是ISO-8859-1,但是對於%和字母數字而言用ISO-8859-1和UTF-8解碼出來的是一樣的,此時就回到了漢字被編碼過一次的字串了,當再次進行解碼的時候使用UTF-8就回將它轉會漢字。