用response得到输出流,即response.getOuptStream(); 返回值为ServletOutputStream 对象,即JSP的out对象,要么用response得到输出对象PrintWriter即response.getWriter()。

Java代码 
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中找到方法说明:

Java代码 
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方法的实现时发现如下代码:

Java代码 
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输出后设定都有效。

///情况三:在tomcat的server.xml中找到Connector的位置,并添加URIEncoding="UTF-8:

<Connector port="8009" protocol="AJP/1.3" redirectPort="8443"URIEncoding="UTF-8"/>

结论:

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),参考:

Java代码 
new PrintWriter(new OutputStreamWriter(new FileOutputStream("yourfilepath"), "UTF-8"));

new PrintWriter(new OutputStreamWriter(new FileOutputStream("yourfilepath"), "UTF-8"));

转自:https://wlbbswl.iteye.com/blog/890377

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

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

    初步实现了Android与pc服务器的通信之后,又碰到了传说中令人头疼不已的中文乱码问题.既然出现了乱码,那么原因自然是协议不通了.我们知道eclipse中默认的编码标准是GBK,而安卓程序开发所默认 ...

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

    中文乱码问题产生的原因,主要就是字符编码设置问题:             首先,mysql数据库安装的时候字符编码要选择正确,最好选择utf-8比较保险.如果安装时没有设置正确,找到mysql的安装 ...

  3. 【原创】python中文编码问题深入分析(二):print打印中文异常及显示乱码问题分析与解决

    在学习python以及在使用python进行项目开发的过程中,经常会使用print语句打印一些调试信息,这些调试信息中往往会包含中文,如果你使用python版本是python2.7,或许你也会遇到和我 ...

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

    问题描述:用android自带的Camera获取图片,上传至远程数据库中(mysql),以BLOB格式存储, 但在提取图片时,始终无法在android界面显示,示例代码如下: .....  .... ...

  5. 左右c++与java中国的垃圾问题的分析与解决

    左右c++与java中国的垃圾问题的分析与解决 DionysosLai(906391500@qq.com)  2014/8/1 问题分析: 之所以会出现中文乱码问题,归根结底在于中文的编码与英文的编码 ...

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

    文<左右c++与java中国的垃圾问题的分析与解决>一bug分析 DionysosLai(906391500@qq.com) 2014/10/21 在前几篇一博客<关于c++与jav ...

  7. JavaScript中的ParseInt("08")和“09”返回0的原因分析及解决办法

    今天在程序中出现一个bugger ,调试了好久,最后才发现,原来是这个问题. 做了一个实验: alert(parseInt("01")),当这个里面的值为01====>07时 ...

  8. SQLServer乱码问题的分析及解决方法(中文字符被存入数据库后,显示为乱码)

    注:本文为个人转存,原文地址:http://blog.csdn.net/qiuyu8888/article/details/8021410 问题:SQL版在使用过程中有时会出现乱码,我的症状是中文字符 ...

  9. Java Web乱码分析及解决方式(一)——GET请求乱码

    引言:     在进行Web開始时.乱码是我们最常常遇到也是最主要的问题.有经验的程序员非常easy能解决,刚開始学习的人则easy被泥潭困住. 并且非常多时候.我们即使攻克了乱码问题也是不明就里.往 ...

随机推荐

  1. iOS-AVPlayer

    MPMoviePlayerController足够强大,几乎不用写几行代码就能完成一个播放器,但是正是由于它的高度封装使得要自定义这个播放 器变得很复杂,甚至是不可能完成.例如有些时候需要自定义播放器 ...

  2. self-attention详解

    编写你自己的 Keras 层 对于简单.无状态的自定义操作,你也许可以通过 layers.core.Lambda 层来实现.但是对于那些包含了可训练权重的自定义层,你应该自己实现这种层. 这是一个 K ...

  3. Jrebel激活方法

    参考 https://www.yanjiayu.cn/posts/3eecb801.html https://gitee.com/gsls200808/JrebelLicenseServerforJa ...

  4. 解决移动端1px的问题,设备像素比devicePixelRatio的应用

    本文主要针对移动端1物理像素问题展开 解决这个问题先要了解一下概念: CSS像素(CSS Pixel):(通俗说:样式中写的值)就是我们在样式代码中常写的逻辑像素,是一个抽象概念,实际并不存在 设备独 ...

  5. Chocolate Eating【二分】

    题目链接:https://ac.nowcoder.com/acm/contest/1577/K 题目大意: 给出n块巧克力,m天吃完.每块巧克力有a[i]快乐值,每天可以选择吃任意块或者不吃巧克力(按 ...

  6. 为什么 Python 中的 True 等于 1

    开始的时候,需要用以下函数来做一个判断,根据返回的值来做一些后续判断处理: def is_success(param): if not param: return False return True ...

  7. 5年经验Java程序员面试20天

      写在前面 今天分享的是一位5年工作经验的Java工程师在帝都的面试经验总结,看看这些互联网公司都爱问些什么题,希望对大家的面试有指导意义. 从事Java开发也有5年经验了,4月初自己的开启面试经历 ...

  8. 纯java代码搭建ssm

    参考: https://blog.csdn.net/Smile__1/article/details/103394460

  9. C++Primer 5th Chap3 Strings,Vectors, and Arrays

    使用名字空间成员的简单方法: using namespace ::name;例如:using std::cin; 头文件不应包含using声明 标准库类型string:(需要带有头文件#include ...

  10. Error:Could not find method google() for arguments [] on repository container

    Error:Could not find method google() for arguments [] on repository container. Consult IDE log for m ...