热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

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

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

在前面的网页中的编码与乱码系列中,曾多次提到使用 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

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


推荐阅读
  • Metasploit攻击渗透实践
    本文介绍了Metasploit攻击渗透实践的内容和要求,包括主动攻击、针对浏览器和客户端的攻击,以及成功应用辅助模块的实践过程。其中涉及使用Hydra在不知道密码的情况下攻击metsploit2靶机获取密码,以及攻击浏览器中的tomcat服务的具体步骤。同时还讲解了爆破密码的方法和设置攻击目标主机的相关参数。 ... [详细]
  • 本文介绍了高校天文共享平台的开发过程中的思考和规划。该平台旨在为高校学生提供天象预报、科普知识、观测活动、图片分享等功能。文章分析了项目的技术栈选择、网站前端布局、业务流程、数据库结构等方面,并总结了项目存在的问题,如前后端未分离、代码混乱等。作者表示希望通过记录和规划,能够理清思路,进一步完善该平台。 ... [详细]
  • 本文总结了淘淘商城项目的功能和架构,并介绍了传统架构中遇到的session共享问题及解决方法。淘淘商城是一个综合性的B2C平台,类似京东商城、天猫商城,会员可以在商城浏览商品、下订单,管理员、运营可以在平台后台管理系统中管理商品、订单、会员等。商城的架构包括后台管理系统、前台系统、会员系统、订单系统、搜索系统和单点登录系统。在传统架构中,可以采用tomcat集群解决并发量高的问题,但由于session共享的限制,集群数量有限。本文探讨了如何解决session共享的问题。 ... [详细]
  • Oracle优化新常态的五大禁止及其性能隐患
    本文介绍了Oracle优化新常态中的五大禁止措施,包括禁止外键、禁止视图、禁止触发器、禁止存储过程和禁止JOB,并分析了这些禁止措施可能带来的性能隐患。文章还讨论了这些禁止措施在C/S架构和B/S架构中的不同应用情况,并提出了解决方案。 ... [详细]
  • MySQL语句大全:创建、授权、查询、修改等【MySQL】的使用方法详解
    本文详细介绍了MySQL语句的使用方法,包括创建用户、授权、查询、修改等操作。通过连接MySQL数据库,可以使用命令创建用户,并指定该用户在哪个主机上可以登录。同时,还可以设置用户的登录密码。通过本文,您可以全面了解MySQL语句的使用方法。 ... [详细]
  • 分享css中提升优先级属性!important的用法总结
    web前端|css教程css!importantweb前端-css教程本文分享css中提升优先级属性!important的用法总结微信门店展示源码,vscode如何管理站点,ubu ... [详细]
  • 如何实现JDK版本的切换功能,解决开发环境冲突问题
    本文介绍了在开发过程中遇到JDK版本冲突的情况,以及如何通过修改环境变量实现JDK版本的切换功能,解决开发环境冲突的问题。通过合理的切换环境,可以更好地进行项目开发。同时,提醒读者注意不仅限于1.7和1.8版本的转换,还要适应不同项目和个人开发习惯的需求。 ... [详细]
  • Servlet多用户登录时HttpSession会话信息覆盖问题的解决方案
    本文讨论了在Servlet多用户登录时可能出现的HttpSession会话信息覆盖问题,并提供了解决方案。通过分析JSESSIONID的作用机制和编码方式,我们可以得出每个HttpSession对象都是通过客户端发送的唯一JSESSIONID来识别的,因此无需担心会话信息被覆盖的问题。需要注意的是,本文讨论的是多个客户端级别上的多用户登录,而非同一个浏览器级别上的多用户登录。 ... [详细]
  • 开发笔记:spring boot项目打成war包部署到服务器的步骤与注意事项
    本文介绍了将spring boot项目打成war包并部署到服务器的步骤与注意事项。通过本文的学习,读者可以了解到如何将spring boot项目打包成war包,并成功地部署到服务器上。 ... [详细]
  • 本文介绍了在sqoop1.4.*版本中,如何实现自定义分隔符的方法及步骤。通过修改sqoop生成的java文件,并重新编译,可以满足实际开发中对分隔符的需求。具体步骤包括修改java文件中的一行代码,重新编译所需的hadoop包等。详细步骤和编译方法在本文中都有详细说明。 ... [详细]
  • SpringMVC工作流程概述
    SpringMVC工作流程概述 ... [详细]
  • PHP函数实现分页含文本分页和数字分页【PHP】
    后端开发|php教程PHP,分页后端开发-php教程最近,在项目中要用到分页。分页功能是经常使用的一个功能,所以,对其以函数形式进行了封装。影视网源码带充值系统,vscode配置根 ... [详细]
  • 面试经验分享:华为面试四轮电话面试、一轮笔试、一轮主管视频面试、一轮hr视频面试
    最近有朋友去华为面试,面试经历包括四轮电话面试、一轮笔试、一轮主管视频面试、一轮hr视频面试。80%的人都在第一轮电话面试中失败,因为缺乏基础知识。面试问题涉及 ... [详细]
  • 在IDEA中运行CAS服务器的配置方法
    本文介绍了在IDEA中运行CAS服务器的配置方法,包括下载CAS模板Overlay Template、解压并添加项目、配置tomcat、运行CAS服务器等步骤。通过本文的指导,读者可以轻松在IDEA中进行CAS服务器的运行和配置。 ... [详细]
  • 本文介绍了在无法联网的情况下,通过下载rpm包离线安装zip和unzip的方法。详细介绍了如何搜索并下载合适的rpm包,以及如何使用rpm命令进行安装。 ... [详细]
author-avatar
宇宇宇你同行
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有