关于Java中字符编码的一点总结

来源:互联网 发布:js脚本 调用 c dll 编辑:程序博客网 时间:2024/06/01 14:31

最近在编写一个servlet上传文件的时候,上网找了一个写好的JspUpload类。能够较好的处理文件上传,但在获取表单中其他Input填写的数据时却得到的乱码,调试的时候发现作者完全忽视了编码的问题。

为此总结一些自己关于编码方面的心得。首先好像Jole讲过这样一句话,大意是:
  当面对一串字节流的时候,如果不指定它的编码,其实际意义是无法知道的。
这句话应该也是我们面对“字符转字节,字节转字符”问题时候时刻记在脑子里的。否则乱码问题可能就接踵而至。
其实乱码问题的本质就是Encoding和Decoding用的不是一个编码,明白了这个道理就很好解决乱码问题了。
 Java中常见的时候有如下:
    1. String类使用byte[]的构造函数 String(byte[] bytes),String类同时提供了两个重载
        String(byte[] bytes, Charset charset)
        String(byte[] bytes, String charsetName) 就是用来指定编码的。

    2. String类的getBytes函数 byte[] getBytes() 同样有如下两个重载:
         byte[] getBytes(Charset charset)
         byte[] getBytes(String charsetName)
       所有不需指定编码的都是使用the platform's default charset, 可使用System.getProperty("file.encoding"),Charset.defaultCharset()获的。
    3. PrintStream的 print(String s)同样设计到这个问题,为此PrintStream的构造函数中除了PrintStream(File file) 还有PrintStream(File file, String csn)
        否则the string's characters are converted into bytes according to the platform's default character encoding,
        DataOutputStream构造时没有方法指定编码,但其提供了一个writeUTF(String str)

举开头的例子说明指定编码的必要:
    如果一个网页指定编码为utf-8, <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />, 页面上有一个form,提交到一个servlet
    那么用户输入的字符传过来的字节流就是按指定编码encoding的,例如你输入了"Hello你好",如果是utf-8,那么传过来的就是如下:
        [104, 101, 108, 108, 111, -28, -67, -96, -27, -91, -67], 我们看到后面汉字每个用了3个字节,这个可以参考Utf-8的相关知识。
    但如果你页面指定的是GBK,那传过来的就不一样了:
        [104, 101, 108, 108, 111, -60, -29, -70, -61]
    所以servlet端,当使用request.getParameter的时候内部应该是调用
        String s = new String(bytes, response.getEncoding())的,如果你response没有设置编码,那么就采用默认的编码null会转为java 平台的GBK,那中文就变成乱码了。
    所以为了避免乱码,jsp站点一般设一个过滤器,所有的页面、servet都设置统一的编码。response.setEncoding, request.setEncoding.

    Java的String内部是一个char[], char是一个用16位存储的utf-16编码的单元。为此,当要把字符、字符串转为字节输出到文件、网络,或者从文件、网络读到的字节流还原为有实际意义的字符,都要明白其编码是什么。