Java servlet 使用 PrintWriter 时的编码与乱码的示例代码

在前面的网页中的编码与乱码系列中,曾多次提到使用 servlet 方式构建的动态响应流,不过在那里都是直接使用字节流的方式,不过,更为常见的方式是使用字符流。而在前面,又谈到了 Java 字节流与字符流的话题。

有了前面的基础,现在来说下 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 时的编码与乱码问题就介绍到这里。本文中的示例代码见:servlet-PrintWriter_jb51.rar

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • jQuery Ajax传值到Servlet出现乱码问题的解决方法

    最近在学jquery ui,在做一个小功能的时候需要将前台的值获取到,通过Ajax传递给Servlet,然后再在返回数据结果,但是在Servlet接受参数的时候,通过后台打印,发现接受乱码,代码示例如下: public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/ht

  • java中Servlet处理乱码的方法

    今天在部署一个webservices程序的时候,从页面获取数据的servlet出现了乱码问题,在servlet中我已经把request.setCharacterEncoding("GB2312");这段文字加入到代码中去,但是还是出现乱麻问题. 到网上找资料,如下:JAVA是Unicode编码,你先转换成ISO8859-1,然后再转换成GBK或是GB2312. java 代码 复制代码 代码如下: request.setCharacterEncoding("ISO8859-1

  • servlet 解决乱码问题

    对于servlet大家应该都很熟悉了,今天再复习一下,如果有哪里写的不好或不对的地点希望广大的网友批评指正.今天只讨论get和post两w种方式,他们之间有很多的不同点,所以解决编码的方式也会不一样,post的乱码问题好解决一点,下面先简单说下http协议,以便我能更好的记忆原理性的东西和他们之间的不同点. get方式和post方式都是基于http协议的,它的目的是为了提供一种发布和接收html页面的方法,由客户端发起请求,服务器端进行响应. 一个完整的请求消息包括:一个请求行,若干消息头和请求

  • 完美解决在Servlet中出现一个输出中文乱码的问题

    如下所示: 在Servlet中出现一个输出中文乱码的问题,已经解. @Override public void doPost(HttpServletRequest reqeust, HttpServletResponse response) throws ServletException, IOException { //PrintWriter out = response.getWriter();在还没有给response指定编码格式时就获取了他的输出流,所以一直乱码 reqeust.setC

  • jsp和servlet操作mysql中文乱码问题的解决办法

    首先看是从什么地方开始出现的乱码,只要统一编码,就不会出现乱码,下面以uft-8(个人认为最好)为例,详细说明: 1.如果乱码是从jsp页面出现的,jsp头部页面加上:<%@ page language="java" pageEncoding="UTF-8" %>在head标签中加上标签. 2.如果乱码是在servlet中出现的,则有两种方法:一种是在每个servlet中doget和doPost方法头部加上request.setCharacterEnco

  • jsp传参 servlet接收中文乱码问题的解决方法

    在公司实习了8个月,一直都是做android和h5的,但是发现做程序连一点服务都不会该怎么办,所以最近开始学起了java,不知道是不是因为框架学多了,现在看起springmvc框架比以前看起来简单太多了,这里我是准备从hibernate开始学习,毕竟数据是根本嘛,首先我用的是hibernate+servlet,但是在jsp页面传参到servlet的时候中文一直乱码,我尝试了好多方法,最后还是解决了. 第一,首先看清项目的编码,jsp页面的编码 第二,修改tomcat 下面的server.xml文

  • Java中HttpServletResponse响应中文出现乱码问题

    以字符串的形式输出. 1.response.getWriter().write("您好中国hello"); 如果这样输出的话.则浏览器结果为: 2.加上代码 response.setCharacterEncoding("UTF-8"); response.getWriter().write("您好中国hello"); 则浏览器结果为: 这是因为浏览器解析问题. 加上代码: response.setHeader("Content-type

  • 关于servlet向mysql添加数据时中文乱码问题的解决

    前言 最近写了一个小Demo,通过 servlet 向 mysql 中添加数据,在 dao 层使用的是 DBUtils 操作的数据库,可是在添加时偏偏出现了中文乱码问题,如下: 添加页面: 点击"添加商品"按钮后,出现中文乱码问题: 问题分析: 1. 难道是 servlet 在接收时没有设置编码格式? 2. 难道是数据传输错误? 3. 难道是浏览器响应时编码问题? 排查: 1.无论是在添加商品的 servlet 中还是在重定向的 servlet 中都设置了编码格式: //设置编码格式

  • HttpServletResponse乱码问题_动力节点Java学院整理

    一个完整的http响应包括响应行,若干响应头和响应数据主体三部分构成.如果我们能用响应对象来进行这三部分的处理,就能向客户发送特定的响应数据包. 先从HttpServletResponse对象的方法中可以看到有如下方法(部分): 这只是一部分,但是我们却可以看出,通过响应对象的方法,我们就能设置响应客户端数据的一些信息.比如setStatus(int sc)方法,我们从HttpServletResponse的API中的字段定义可找到已经设置好的响应码(部分): 我们通过setHeader或者ad

  • javaweb servlet中使用请求转发乱码的实现

    乱码的方式有很多,这里指出一种不容易想到的 *请确保您的页面单独访问正常,经过servlet请求转发时,有PrintWriter out = response.getWriter()不正常,没有正常 解决方式是在执行PrintWriter out = response.getWriter();前加上 response.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=utf-8&

随机推荐