java 中 byte 8位  char16位;


String 里面用unicode储存的;


toBytes("编码") 是将unicode先转换为指定"编码"再变为byte[],找不到对应的就为:3F;


new String(a,"编码")  : a byte[] 表示的东西是"编码", 要将他转换为unicode并存入string,当然这种转换unicode全部笑纳,不会找不到对应字符;


在处理一般字符串的时候没什么问题,如果用来做数据加密和二进制操作时(如zip压缩,base64编码,数字签名),就需要用到,byte[]来处理这些二进制,而有时也可以使用String,这是需要用到iso-8859-1;


因为iso-8859-1到unicode的双向转换都可以完全映射,故iso-8859-1可以用来保存任何的byte[]到string, 再转换出来和原来的一致。如果有个二进制,并非文字的byte[] ,只要用iso-8859-1存入string就可以保存,toBytes出来和原来的byte[]一样。iso8859到unicode的转换就是将每一字节前但应加上一个00,字节长度增加为2倍。


接下来做一下jsp的编码问题测试:

测试环境 IE8 tomcat6 jdk6

表单Jsp:

<form action = "servlet1" >
    <input type="text" value="" name="a"/>
    <input type="submit" value="ok" />
</form>


printBytes("编码:", req.getParameter("a").getBytes("unicode"));


printBytes用来测试服务端收到的字节,这个最直接的读取string内部值:

public  void printBytes(String title, byte[] data)
    {
        System.out.println(title);
        for (byte b : data)
        {
            System.out.print(toHexString(b) + " ");
        }
        System.out.println();
    }

    public  String toHexString(byte value)
    {
        String tmp = Integer.toHexString(value & 0xFF);
        if (tmp.length() == 1)
        {
            tmp = "0" + tmp;
        }

        return tmp.toUpperCase();
    }



jsp 的有关参数,3个

tomcat server.xml的useBodyEncodingForURI 和URIEncoding,相关文档http://tomcat.apache.org/tomcat-5.5-doc/config/http.html

这两个参数是互斥的,前者优先级高,覆盖后者配置,请注意

他们指的是提交到服务器的uri的编码,也就是让tomcat将收到的包含%34%AD这样的表示中文的uri如何填入String,让req.getParameter调用;URIEncoding直接告诉tomcat用什么编码,useBodyEncodingForURI 间接说明用bodyencoding的编码来处理uri,而get方式提交的form就放在uri里,所以get方式与这两个参数有关, post方式与此二参数无关。


什么是bodyencoding?,及req.setCharacterEncoding("utf-8"); ;如果定义了req.setCharacterEncoding又定义了useBodyEncodingForURI ,说明post和get方式提交过来的处理方式一致。


<%@ page contentType="text/html;charset=utf-8" language="java" %>

这个配置信息和服务端无关,他是告诉浏览器这个页面是什么编码,浏览器则决定“展示到Windows前端gbk需不需要转换"。浏览器在提交后续页面时的编码行为,都受此控制,发送出去的所有内容(post,get)都按照这个来编码再发往服务器。


req.setCharacterEncoding("utf-8")

指定服务器的行为。让服务器将发过来请求视为XX编码,以此编码将post数据写入String。语句放在接收form的servlet.java文件中,getParameter之前


经过大量测试,学习到很多东西,主要的测试结果及说明:

1.tomcat两个参数均未设置,页面page contentType utf-8,方式GET

输入中国,UTF-8编码是E4 B8 AD E5 9B BD

打印输出到命令行的是:FE FF 00 E4 00 B8 00 AD 00 E5 00 9B 00 BD

说明服务端req.getParameter得到的是UTF-8被误当作ISO-8859-1而生成的String。
说明浏览器按utf-8发送,服务端因未设置而当作iso-8859-1,这样开发开发时需要new String(req.getParameter("a").getBytes("iso-8859-1"),"utf-8")也能解决,可以继续开发,但不太完美。


2.tomcat URIEncoding="utf-8",页面page contentType utf-8,方式GET
正确!浏览器把字段转换为utf-8的字节串发送,服务端在uri中将%xx%xx转换为二进制字节串,再以utf-8格式读入String


3.tomcat useBodyEncodingForURI,相应action 的servlet req.setCharacterEncoding("utf-8"),方式GET
正确!浏览器把字段转换为utf-8的字节串发送,服务端在uri中将%xx%xx转换为二进制字节串,再以utf-8格式统一处理URI和POST,读入String。

让浏览器知道get  uri中的字符原来是什么编码需要这两个参数一起指定,或用tomcat URIEncoding一个参数替代。


4.以上第3点中两个条件缺少一个就会获得UTF-8被误当作ISO-8859-1而生成的String,即服务端将uri当作iso8859了


5.tomcat URIEncoding="utf-8",页面page contentType utf-8,方式POST
UTF-8被误当作ISO-8859-1而生成的String。因为post参数欲uri无关,而有没有设置req.setCharacterEncoding


6.tomcat 两参数未设置,相应action 的servlet req.setCharacterEncoding("utf-8"),方式POST
正确! 告诉服务器POST来的数据是什么编码只需req.setCharacterEncoding