我們常常遇到字符集轉換的問題。
我要說的當然不是網站中遇到的ISO8859-1的那個傻BUG。
實例:
目標,把一個UTF-8的中文字符串轉化成GBK的字符串。
新建一個GBK的java項目。
也就是說*.java文件中的字符是用GBK字符集保存的。
在main中,建一箇中文字符串,那麼這個靜態串就是GBK字符。
再把它的屬性,字符集改成UTF-8後,變成這樣了。
然後,我們再建一個UTF-8的java項目。
在main中寫入以下:
String str = "新建文本文檔.txt";
System.out.println(str);
byte[] bs = null;
try {
bs = str.getBytes("UTF-8");
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
System.out.print( "UTF-8: \n");
for(int i=0;i<bs.length;i++){
System.out.print( bs[i] + " ");
}
System.out.println();
try {
String tempStr ="";
bs = str.getBytes("GBK");
System.out.print( "GBK: \n");
for(int i=0;i<bs.length;i++){
System.out.print( bs[i] + " ");
}
System.out.println();
System.out.println();
tempStr = new String(bs,"GBK");
System.out.println( "用UTF-8打印,這個GBK串(通過GBK重組後的): "+ tempStr );
tempStr = new String(bs,"UTF-8");
System.out.println( "用UTF-8打印,這個GBK串(通過UTF-8重組後的): "+ tempStr );
System.out.print( "再把這個串"+tempStr+"轉成UTF-8數組打印: \n");
bs = tempStr.getBytes("UTF-8");
for(int i=0;i<bs.length;i++){
System.out.print( bs[i] + " ");
}
System.out.println();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
得到的輸入:
很明顯,通過GBK重組後的字符串,打印出來的是明文,與我們原選做的測試完全不一樣。
也就是說他根本沒有被轉碼。
而通過UTF-8重組後的字符串,打印出來的才與我們原先看到的測試是一樣的。
這纔是真正的轉碼成功了。
這是爲什麼呢?
JDK幫助的描述是這樣的。
getBytes(Charset charset)
使用給定的 charset 將此 String 編碼到 byte 序列,並將結果存儲到新的 byte 數組。
String(byte[] bytes, Charset charset)
通過使用指定的 charset 解碼指定的 byte 數組,構造一個新的 String。
應該這樣理解:
getBytes是真正的在轉碼。
而new String是把它用某種碼來顯示。
像上面的那串亂碼,它正在已經是GBK碼了,用GBK顯示正常,用UTF-8顯示是亂碼。
但,現在我們是在UTF-8環境下,所以要用UTF-8存字符串,最後把這個串輸出給讀它的平臺。
你可以用,Xshell 的兩種字符集環境來打印以上的輸出。
在GBK連接的方式中,那串亂碼被正常顯示出來。
你感興趣,還可以把這個例子反過來做一下,看是不是你想要的結果。
同時,我們再來理解一下tomcat中爲什麼要做這樣一件事:
new String(str.getBytes("ISO-8859-1"),"gb2312");
這是因爲,默認情況下,tomcat使用的是iso8859-1的編碼方式傳遞。
而網頁中設定的比如是gb2312或utf-8。這樣得到的就是錯的。
所以用ISO-8859-1得到字節流,再用gb2312來重組字節流得到gb2312的字符串流。
解決辦法:
修改tomcat下的conf/server.xml文件
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
修改爲:
<Connector port="8080" useBodyEncodingForURI="true" URIEncoding="UTF-8" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />