我们常常遇到字符集转换的问题。
我要说的当然不是网站中遇到的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
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
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
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文件修改为: