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数据。