用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. 【计算机视觉】Selective Search for Object Recognition论文阅读1

    Selective Search for Object Recognition 作者: J. R. R. Uijlings, K. E. A. van de Sande, T. Gevers, A. ...

  2. 扩展方法和Enumerable

    .NET中扩展方法和Enumerable(System.Linq) LINQ是我最喜欢的功能之一,程序中到处是data.Where(x=x>5).Select(x)等等的代码,她使代码看起来更好 ...

  3. Redis集群部署与维护

    Redis集群部署与维护 目录: 一. 集群架构 二. 集群部署 1. 创建redis-cluster目录 2. 编译redis 3. 编辑redis配置文件 4. 配置redis集群 5. redi ...

  4. uwp,GridView、ListView取消选中效果

    在SelectionChanged事件中,添加两行代码,取消点击Item后的选中效果 void GridViewSelectionChanged(object sender, SelectionCha ...

  5. 搭建apache2.4+php7+mysql+phpmyadmin

    apache2.2不支持php7,会报错 cannot load php7apache2_4.dll into server 前排提示:保证安装文件夹和我的一致可以省事很多哦 下载地址 下载apach ...

  6. Oracle数据库——用户(USER)

    前言   本文将介绍小白入门级别的关于用户的SQL语句.想全面了解的请参考其他资料.例如:Oracle官方文档--CREATE USER 文章目录 前言 创建用户 修改用户密码 授予用户权限 删除用户 ...

  7. java 用户线程和守护线程

    在Java中通常有两种线程:用户线程和守护线程(也被称为服务线程)通过Thread.setDaemon(false)设置为用户线程通过Thread.setDaemon(true)设置为守护线程线程属性 ...

  8. QMetaMethod 获取成员函数的元信息

    在上一篇中,我们将的是QMetaEnum类,它可以获得一个类中由Q_ENUM宏或Q_FLAG宏声明的枚举类型的元信息.同样,QMetaMethod类是用来获取成员方法的元信息的一个类.通过该类,我们可 ...

  9. 利用jwt生成token,用于http请求身份验证

    前段时间在做移动端接口过程中,考虑到安全性,所有移动端发送请求(除了登录请求)过程中进行token有效验证. 1.利用jwt生成token a.导入jwt相关包 <!-- jwt --> ...

  10. 生成 excel 插件 Epplus

    最近做 .net core 项目 发现一个新的 生成excel 的插件 . 以前值用 aspose 或者 npio. 简介:Epplus是一个使用Open Office XML(Xlsx)文件格式,能 ...