PrintWriter返回乱码的分析及解决

protected void doGet(HttpServletRequest request,     
    HttpServletResponse response) throws ServletException,  
        IOException { 

    PrintWriter pw = response.getWriter();       
    response.setCharacterEncoding("utf-8");       
    response.setContentType("text/html; charset=utf-8");       
    pw.print("中文");
}
 protected void doGet(HttpServletRequest request,       
    HttpServletResponse response) throws ServletException,IOException {   
   
     PrintWriter pw = response.getWriter();         
     response.setCharacterEncoding("utf-8");         
     response.setContentType("text/html; charset=utf-8");         
     pw.print("中文");  
  } 

输出乱码。为什么呢,已经设置了字符编码啊?难道设置的无效。

在API中找到方法说明:

 PrintWriter getWriter() throws IOException   
     
   Returns a PrintWriter object that can send character text to the client. The PrintWriter uses the character encoding returned by getCharacterEncoding().   
  
   If the response‘s character encoding has not been specified as described in getCharacterEncoding (i.e., the method just returns the default value ISO-8859-1), getWriter updates it to ISO-8859-1.
PrintWriter getWriter() throws IOException 

Returns a PrintWriter object that can send character text to the client. The PrintWriter uses the character encoding returned by getCharacterEncoding(). 

If the response‘s character encoding has not been specified as described in getCharacterEncoding (i.e., the method just returns the default value ISO-8859-1), getWriter updates it to ISO-8859-1.

就是讲,在返回一个PrintWriter对象的时候,charactor encoding就已经确定了,就已经设置好了字符集了。什么时候设置的呢? setCharacterEncoding方法的实现时发现如下代码:

 public void setCharacterEncoding(String charset) {      
     
        if (isCommitted())      
            return;  
             
      // Ignore any call from an included servlet      
        if (included)      
            return;  
             
       // Ignore any call made after the getWriter has been invoked      
        // The default should be used      
       if (usingWriter)      
           return;  
    
             coyoteResponse.setCharacterEncoding(charset);      
      isCharacterEncodingSet = true;  
  }
public void setCharacterEncoding(String charset) {    
   
        if (isCommitted())    
            return;
            
        // Ignore any call from an included servlet    
        if (included)    
            return;
            
        // Ignore any call made after the getWriter has been invoked    
        // The default should be used    
        if (usingWriter)    
            return;
   
        coyoteResponse.setCharacterEncoding(charset);    
        isCharacterEncodingSet = true;
    }

其中usingWriter 标志为getPrinteWriter方法中设定,可见其控制逻辑为一旦返回了PrintWriter,本函数即不再生效。

ServletOutputStream out = response.getOutputStream();

out.print("中文");

情况1:正常,浏览器按utf-8方式查看
//response.setContentType("text/html; charset=utf-8");
            
情况2:浏览器缺省按简体中文查看,手动设为utf-8方式查看正常
//response.setCharacterEncoding("utf-8");
说明:这种方式不仅不需要在调用getOutputStream()之前设定字符集,甚至在print输出后设定都有效。

结论:

1.在servlet中输出中文,如果采用PrintWriter方式,需要在调用getPrintWriter()之前调用setContentType 或者 setCharacterEncoding;采用ServletOutputStream方式,不受此限。

2.setContentType 和 setCharacterEncoding两方法中设定characterEncoding的方法对服务器效果一致,不需要反复调用。在输出文本内容时, 采用response.setContentType("text/html; charset=utf-8");似乎更为方便。

3.PrintWriter自身并没有处理编码的职责,它还是应该看成一个装饰器比较好:它就是为了输出更方便而设计的,提供print、 println、printf等便利方法。要设置编码的话,可以在它的底层Writer上设置:(这里以OutputStreamWriter为底层 Writer),参考:

new PrintWriter(new OutputStreamWriter(new FileOutputStream("yourfilepath"), "UTF-8")); 
时间: 2024-10-23 23:24:49

PrintWriter返回乱码的分析及解决的相关文章

关于c++与java中文乱码问题分析与解决

关于c++与java中文乱码问题分析与解决 DionysosLai([email protected])  2014/8/1 问题分析: 之所以会出现中文乱码问题,归根结底在于中文的编码与英文的编码方式存在差异. 在java内部是使用16bit的unicode编码(即utf-16)来表示字符串,无论英文还是中文都是2字节. C/C++使用的是原始数据,ascii是一个字节,中文一般是GB2312编码,用2个字节表示一个汉字. Jni内部是使用utf-8编码表示字符串的,utf-8是扁长的unic

文《关于c++与java中文乱码问题分析与解决》中一个bug分析

文<关于c++与java中文乱码问题分析与解决>中一个bug分析 DionysosLai([email protected]) 2014/10/21 在前几篇一博客<关于c++与java中文乱码问题分析与解决>,地址如下:http://blog.csdn.net/dionysos_lai/article/details/38389765.文中详细介绍了c++与java数据传递时,为何会出现中文乱码的原因,并提出了适当的解决方法.方法如下: int CCDirector::GBKTo

关于Android与pc通信时中文乱码的分析和解决

初步实现了Android与pc服务器的通信之后,又碰到了传说中令人头疼不已的中文乱码问题.既然出现了乱码,那么原因自然是协议不通了.我们知道eclipse中默认的编码标准是GBK,而安卓程序开发所默认的布局文件编码标准则是utf-8,这样一来,我们双方通信的时候便难免出现乱码.要解决它,就要从二者转换方面着手.     首先我们知道,从安卓手机界面上获得的文字,其编码字符集是utf-8,所以,当我们的java文件获得它时,它是以utf-8形式编译的.所以这里,在得到EditText中的文字之后,

php中文乱码问题分析及解决办法

中文乱码问题产生的原因,主要就是字符编码设置问题: 首先,mysql数据库安装的时候字符编码要选择正确,最好选择utf-8比较保险.如果安装时没有设置正确,找到mysql的安装目录,修改my.conf配置文件中的字符设置,打开文件,应该一个是在mysqll下面,一个是在server下面的. 如果是php页面的中文乱码,也就是非数据库查询出来的数据,HTML页面静态的部分出现乱码,应该使用header("content-type:text/html; charset=utf8") 来设定

项目乱码的分析与解决

一.设置新建常见文件的默认编码格式,也就是文件保存的格式. 在不对MyEclipse进行设置的时候,默认保存文件的编码,一般跟简体中文操作系统(如windows2000,windowsXP)的编码一致,即GBK. 在简体中文系统下,ANSI 编码代表 GBK编码;在日文操作系统下,ANSI 编码代表 JIS 编码. Window-->Preferences-->General -->content Types 在右侧窗口中展开每一个子项,依次输入编码格式,如“UTF-8”点击“updat

BitmapFactory.decodeByteArray() 返回null,分析与解决

问题描述:用android自带的Camera获取图片,上传至远程数据库中(mysql),以BLOB格式存储, 但在提取图片时,始终无法在android界面显示,示例代码如下: .....  .... s = new Socket("192.168.0.68", 9999);   din = new DataInputStream(s.getInputStream()); ...   ... int size = din.readInt();//读取服务器端传来的图片数据   byte[

文《左右c++与java中国的垃圾问题的分析与解决》一bug分析

文<左右c++与java中国的垃圾问题的分析与解决>一bug分析 DionysosLai([email protected]) 2014/10/21 在前几篇一博客<关于c++与java中文乱码问题分析与解决>.地址例如以下:http://blog.csdn.net/dionysos_lai/article/details/38389765.文中具体介绍了c++与java数据传递时.为何会出现中文乱码的原因,并提出了适当的解决方法. 方法例如以下: int CCDirector::

JavaScript中的ParseInt(&quot;08&quot;)和“09”返回0的原因分析及解决办法

今天在程序中出现一个bugger ,调试了好久,最后才发现,原来是这个问题. 做了一个实验: alert(parseInt("01")),当这个里面的值为01====>07时都是正常的,但是在"08","09"就会返回0 (这种现象出现在ie内核的浏览器中,如360浏览器就会出现这种错误)(谷歌,火狐不受影响). 查阅资料得知着这种现象原因: 大神的解释: 01--07自然没有问题,但是09,08都是不合格的八进制形式,所以被按照0处理了.

【javascript】浮点数运算问题分析及解决方法

问题: 在用 js 进行小数四则运算时发现了一个重大问题,比如:0.7 * 0.8 = 0.5599999999999999 分析: 在 js 中只有一种数字类型 Number,而且在 js 中所有的数字都是以 IEEE-754 标准格式表示的.浮点数的精度问题并不是 js 特有的,因为有些小数以二进制表示位数是无穷的,比如 1.1,其程序实际上无法真正的表示 1.1,而只能做到一定程度上的准确(1.09999999999999999),这是无法避免的精度丢失. 通过 chrome 控制台,我们