Java servlet使用PrintWriter时的编码与乱码怎么办
这篇文章主要介绍Java servlet使用PrintWriter时的编码与乱码怎么办,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!
现在来说下 Java servlet 中使用字符流,也即是 PrintWriter 时的编码与乱码问题。
回顾字节流的情形
先回顾一下,在之前的字节流响应中,我们使用 String.getBytes 方法,然后总是显式传入编码的参数,使它与 meta 中或者 header 的声明一致。比如这样:
或者这样:
只要保持了一致,就不用担心发生乱码的问题。
使用 PrintWriter 字符流,缺省编码
现在假如使用 PrintWriter 来作为响应呢?比如这样:
代码中并没有显式传入什么编码的参数,不像 String.getBytes 那样。另一方面,我们知道,字符流最终还是要转换成字节流,可是它到底使用了什么编码呢?是不是 Charset.defaultCharset 中的值呢?
就以上述代码为例,假如现在在浏览器中查看,会发现结果是这样的:
可见 defaultCharset 缺省是 utf-8,前面说过,这其实来自于启动 tomcat server 时所传入的参数 –Dfile.encoding:
但汉字却没有正确输出,可见 PrintWriter 并没有采用这个缺省值。查看 header 中的响应:
也没有任何编码的指示。
虽然 meta 中声明是 utf-8,输出的缺省字符集的值也是 utf-8,可是从最终结果不难看出 PrintWriter 并没有采纳这个值来转换字节流。(实际上它根本不会试图去理解这个)。
看一看它的文档说明,会发现情况有点不一样:
原来没有指定时,PrintWriter 不是用 Charset.defaultCharset 中的值,而是用 response.getCharacterEncoding 方法中所返回的值,而没有指定的话,那个方法其实就返回一个缺省值:ISO-8859-1。
再看看 getCharacterEncoding 方法:
可以看到它的值又是来源于显式的 response.setCharacterEncoding 或 response.setContentType 方法,或者是隐式的 setLocale 方法。(显式的具有更高的优先级)假如没有,就用缺省的 ISO-8859-1。
它还提到 RFC 2047 标准 ,打开看看,是关于 MIME 中非 ASCII 文本的消息头扩展(MIME (Multipurpose Internet Mail Extensions) Part Three: Message Header Extensions for Non-ASCII Text)的。文中有一处提到如果字符集编码缺失,推荐用 iso8859 系列:
注意这里没有明说是 iso-8859-1,它说的是 iso-8859-*,不过 servlet 最终采用的是 iso-8859-1.
所以现在清楚了,缺省用 iso-8859-1,可以用 getCharacterEncoding 得到它的值,不过 iso 不支持中文字符,所以响应流中不能出现中文:
结果是这样:
使用 PrintWriter 字符流,显式指定编码
按照前面说的,可以在 write 之前使用 setCharacterEncoding 等方法指定编码:
这样就 OK 了:
要注意,这种情况下,response header 中仍然没有 charset 信息,所以要在 meta 中指定。
也可以用 setContentType (或前面一直用的 setHeader,其实两者是等价的):
也能达成同样效果:
这种情况下,response header 中包含 charset 信息,所以前面的代码中可以省略在 meta 中的声明:
那么,现在我们明白了,PrintWriter 的缺省与普通字符流的缺省是不同的,机制有所差别。
使用普通字符流,缺省编码
当然如果你一定要用普通字符流,也是可以的,但最后需要主动 flush:
这时的缺省就是 Charset.defaultCharset 中的值了,这里把它拼在了 meta 和最终的输出中,响应也是正常的:
结果是 utf-8。跟前面所说的 tomcat server 启动时参数的值一致。
使用普通字符流,显式指定编码
如果不打算用缺省,那就直接指定:
结果同样是 OK 的:
当然,一般还是建议使用 PrintWriter 来输出,而即便你一定要用普通字符流,也最好不要用缺省。
以上是“Java servlet使用PrintWriter时的编码与乱码怎么办”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注编程网行业资讯频道!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341