web开发中的中文问题
jetty处理的总结
http://docs.codehaus.org/display/JETTY/International+Characters+and+Character+Encodings
结论:
import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.Map; import java.util.Properties; /** * 结论:在使用页面编码为gbk时:<br> * get时:ajax提交:firefox.ajax.get使用URLEncode(utf8)(但存在bug,见下),ie使用String.getByte( * 页面编码).注:此时charset不可信<br> * get时:form提交:ie,firefox使用页面编码(当前为gbk).注:此时charset没数据<br> * post时:ajax提交:ajax提交firefox、ie使用String.getByte(utf8)编码.注:此时charset不可信<br> * post时:表单提交:使用页面编码.注:此时charset没数据<br> * * firefox.ajax.post请求,在context-type的charset会自动设置为utf-8,无论你写什么。后台拿数据则通过utf-8 * 取得正确数据 ie.ajax.post请求,在context-type不设置情况下,后台拿默认charset(gbk)时解析出错。 * * 问题: 默认URIEncode使用ISO-8859-1,如何得到正确中文?: 答:自行将取出String.getByte(ISO-8859-1),再new * String(gbk)<br> * * jetty默认对uri使用utf8编码,如果希望其他编码方式,在jetty启动时设置:-Dorg.mortbay.util.URI.charset=gbk * tomcat默认对uri使用iso-8859-1编码,如果希望其他编码,配置connector的URIEncoding=gbk * * 问题: firefox为什么在页面编码gbk下ajax.post可行而ie不行? * 答:firefox下ajax.post传输的是utf-8,context-type中charset不允许用户修改,就算用户设置了,仍为utf-8 * ie下ajax.post传输的是utf-8,但是context-type的charset允许设置或默认按页面编码,如果页面编码是gbk就出错了。 * * firefox.ajax.get的bug情况: * firefox默认情况是按URLEncode(utf8)的,但是如果下拉框默认有数据,则按页面编码gbk发送,此时charset不可信 * * * * @author W_jiangyongyuan * */ public class Test { public static void main(String[] args) throws UnsupportedEncodingException { Test t = new Test(); // t.utf8_ajax_post(); // t.utf8_form_get_post(); // t.get_ajax_gbk_firefox(); // t.get_ajax_gbk_ie(); // t.change_charset(); // t.change_charset2(); t.change_charset3(); // t.change_charset4(); } String s = "中高风险"; /** * ie下ajax.get按页面编码,不使用charset * * @throws UnsupportedEncodingException */ void get_ajax_gbk_ie() throws UnsupportedEncodingException { String value = new String(s.getBytes("UTF-8"), "GBK");// 传输了utf8,转成gbk,firebug界面看到的乱码 String value2 = new String(URLEncoder.encode(s, "GBK") .getBytes("UTF-8"));// 传输了utf8,转成gbk,firebug界面看到的乱码 System.out.println(value2); } /** * firefox下ajax.get按charset编码,通过URLEncode(charset)调用 * * @throws UnsupportedEncodingException */ void get_ajax_gbk_firefox() throws UnsupportedEncodingException { System.out.println(URLEncoder.encode(s, "UTF8"));// %D6%D0%CE%C4 } /** * form点击按钮提交,编码按页面编码并通过URLEncodeer提交。 * get,post一致,ie,firefox一致,URLEncoder(gbk) * * @throws UnsupportedEncodingException */ void utf8_form_get_post() throws UnsupportedEncodingException { System.out.println(URLEncoder.encode("中文", "GBK"));// %D6%D0%CE%C4 } /** * ajax.post方式,全部用utf8编码,无论是否设置了context-type中的charset为其他数据<br> * ie,firefox一致,String.getByte("utf-8") * * @throws UnsupportedEncodingException */ void utf8_ajax_post() throws UnsupportedEncodingException { System.out.println("test utf8 post"); String value = new String(s.getBytes("UTF-8"), "GBK");// 传输了utf8,转成gbk,firebug界面看到的乱码 System.out.println(value); } /** * utf-8错误转成gbk后可能可以正确转回,当字符为2的倍数时。因为utf-8码中文为三个字符 * @throws UnsupportedEncodingException */ void change_charset2() throws UnsupportedEncodingException { String s = "中文"; printByte("utf-8", s); String s2 = new String(s.getBytes("utf-8"), "gbk"); printByte("gbk", s2); String s3 = new String(s2.getBytes("gbk"), "utf-8"); printByte("utf-8", s3); //如果s只有一个字符,则无法转回 } /** * gbk错误转成utf8后无法正确转回 * @throws UnsupportedEncodingException */ void change_charset3() throws UnsupportedEncodingException { String s = "中文"; printByte("gbk", s); String s2 = new String(s.getBytes("gbk"), "utf-8"); printByte("utf-8", s2); String s3 = new String(s2.getBytes("utf-8"), "gbk"); printByte("gbk", s3); System.out.println(s3); } /** * gbk数据错误转成iso-8859-1后可以正确转回gbk * @throws UnsupportedEncodingException */ void change_charset4() throws UnsupportedEncodingException { String s = "中文"; printByte("gbk", s); String s2 = new String(s.getBytes("gbk"), "iso-8859-1"); printByte("iso-8859-1", s2); String s3 = new String(s2.getBytes("iso-8859-1"), "gbk"); printByte("gbk", s3); } void printByte(String charset, String s2) throws UnsupportedEncodingException { System.out.println(s2); System.out.println("\nnow is " + charset); for (Byte b : s2.getBytes(charset)) { System.out.print(Integer.toHexString(b)); } System.out.println("\n"); } }
上面代码中的change_charset中,测试证明
对于错误转码的情况,将gbk码的字符错误当成utf-8后,无法恢复gbk.因为byte数据已经改变。
而iso-8859和gbk时却不会改变乱码的byte数据。