0

0

JAVA WEB 笔记--中文乱码

巴扎黑

巴扎黑

发布时间:2017-06-26 11:11:01

|

1857人浏览过

|

来源于php中文网

原创

java web 乱码问题解析

乱码原因

  在java web开发过程中,经常遇到乱码的问题,造成乱码的原因,概括起来就是对字符编码和解码的方式不匹配。

  既然乱码的原因是字符编码与解码的方式不匹配,那么为什么我们一定要对字符进行编码,不编码可不可以呢?这是因为在计算机中存储数据的基本单位是1个字节,即8个bit,那么它所能表达的字符的最多有28=256个,而在我们现实社会中存在的字符(汉字、英文、其他文字等等)远远多余这个数字,所以为了解决字符与字节的矛盾,对字符进行编码处理才能存储在计算机中。

编码与解码

  在计算机中常见的编码方式有ASCII、ISO-8859-1、GB2312、UTF-16、UTF-8几种编码方式。

  ASCII码是使用一个字节的低7位来表示的,所以共能表达的字符最多有27=128个。ISO-8859-1是ISO组织基于ASCII码的基础上扩展来的,兼容ASCII码,涵盖了大多数西欧字符。ISO8859-1使用一个字节来表示,所以其能表达的字符最多有256个。GB2312,采用了双字节编码,编码范围是A1-F7,其中A1-A9是符号区,B0-F7是汉字区,包含6763个汉字。GBK是为了扩展GB2312编码,并加入了更多的汉字,总能表达的汉字有21003个。UTF-16是采用定长的编码方式,无论什么字符都采用2个字节进行表示,这也是JAVA内存中字符的存储格式。与UTF-16相反,UTF-8采用了变长的编码方式,不同的类型的字符可以由1-6个字节组成。

   下面以字符串“日向雏田”来看一下在计算机中不同编码方式的编码,如下图。

立即学习Java免费学习笔记(深入)”;

 

乱码分析与解决

  对于JAVA WEB中乱码问题,我们划分位请求导致的乱码和响应导致的乱码,对于不同的乱码我们要分析其乱码原因,即字符编码的方式是什么,解码的方式是什么。

  对于由于请求导致的乱码我们要分析Http请求,查看其编码方式,由于HTTP请求分为Get请求和Post请求,我们接下来分别对其进行讨论。

  对于Get请求,是浏览器默认的请求方式,和表单提交时设置为“Get”时的提交方式。我们通过火狐浏览器我们查看其具体内容如下:

  地址栏为:

  请求内容为:

  

  通过上面请求我们可以看到,GET请求中查询字符串放在了请求行中存放,发送到WEB服务器中,通过“日向雏田”编码我们可以看到,浏览器对该字符串采用的编码方式为“UTF-8”。

  查看服务器代码我们可以看到乱码(如下图),这是因为服务器在接受到该字符串编码后的数据默认通过ISO-8859-1的方式进行解码,所以造成了编码与解码的方式不统一。

  

  解决方案如下:

  首先获取字符串user解码前的编码,然后指定该字符串的编码方式,如下图:

  解决方案示意图如下:

 

  在Java web开发过程中,我们在超链接中传递参数,经常遇到中文的情况。对此情况下,我们需要对中文进行编码,我们可以设置为UTF-8,解码方案同上。

  

<a href="${pageContext.request.contextPath}/Test?user=<%=URLEncoder.encode("日向雏田", "UTF-8")%>">点击</a>

  对于Post请求,是表单提交时设置为“Post”时的提交方式。我们通过火狐浏览器我们查看其具体内容如下:

  地址栏及其页面为:

  

  post请求内容为:

  

  由上图我们可以知道,在post请求中,将请求内容直接放在请求体中发送给web服务器,编码方式为“utf-8”。

  在此响应Servlet中,doPost方法体如下:

  

SoundRaw AI
SoundRaw AI

面向创作者的 AI 音乐生成器,只需选择情绪、流派和长度,SoundRaw AI就能为你生成优美的歌曲。

下载
public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String user=request.getParameter("user");
		System.out.println(user);//输出为æ&#151;¥å&#144;&#145;é&#155;&#143;ç&#148;°
	}

 

  此处乱码的原因依然时在代码getParameter(“user”)时,web服务器采用默认的解码方案“ISO-8859-1”进行解码,导致了编码与解码方案的不同意,解决方案可以采用get请求乱码的解决方案,但是还有一种更为简单的解决方案,直接指定方法体的编码/解码方案为“utf-8”。方案如下。

  

public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setCharacterEncoding("utf-8");  //设置请求体的编码/解码方案为UTF-8 但是请求行的编码解码方案不会受影响
		String user=request.getParameter("user");
		System.out.println(user);          //输出为日向雏田
	}

   以上对于请求导致的乱码情况分析完毕。

  在影响导致的乱码中,web服务器会将响应的内容写入响应体中,返回给客户端并不会涉及到状态行中的情况。如向浏览器输出”HelloWorld“其响应如下图所说。

  对于响应导致的乱码我们不得不涉及到四个方法,如下:

 

response.setHeader("Content-Type", "text/html;cahrset=utf-8");//设置发送到客户端的响应的内容类型和响应内容的编码类型(响应体的编码类型)
response.setCharacterEncoding("utf-8");//设置响应体的编码类型
response.getWriter();           //获取响应的输出字符流 
response.getOutputStream();        //获取响应的输出字节流

 

  对于设置响应体的编码类型,如response.setHeader("Content-Type", "text/html;cahrset=utf-8");与response.setCharacterEncoding("utf-8");这2个方法设置的编码方式等效,若没有设置响应体的编码方式,则默认为ISO-8859-1,而且后面设置响应体字符的编码方式会迭代前面的设置编码的方式。这两个方法均在getWriter方法前有效,在getWriter方法设置编码的方法会无效。

  但是这2个方法却有点不同,即setHeader("Content-Type", "text/html;cahrset=utf-8")这个方法浏览器会自动采用该响应体的编码方式进行解码,而setCharacterEncoding()该方法并不是所有的浏览器都会采用该方法的编码方式进行解码,下面对这2个方法进行测试,效果如下:

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setHeader("Content-Type", "text/html;charset=utf-8");
		response.getWriter().write("日向雏田");
	}

  

  

public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setCharacterEncoding("utf-8");
		response.getWriter().write("日向雏田");
	}

  

 

   从上面可以看到第一个方法对于浏览器来说,支持的较好,提倡采用第一种方法设置响应体的字符编码方式。

  对于获取响应字符输出流的方法,如果在此之前没有设置响应体的编码方式,那么默认为null,即ISO-8859-1方式进行编码。而且后面设置的编码方式会覆盖前面设置的编码方式。在getWriter()方法之后设置的编码无效。

  对于获取响应输出字节流,我们在输出字符串时,我们需要设置字符串的编码方式如果没有那么默认ISO-8859-1。

  对于前面2个输出流,由于只有一个输出缓存,所以这两个方法互斥。

  以上,为了保证响应无乱码,需要保证字符编码和解码方法的统一,方案如下:

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
//	方案1
//		response.setHeader("Content-Type", "text/html;charset=utf-8");
//		response.getWriter().write("日向雏田");
//	方案2
//		response.getOutputStream().write("日向雏田".getBytes("UTF-8"));
//	方案1,2互斥
	}

  

   此外在Java web开发过程中,我们还会遇到当进行文件下载时,中文文件名导致的问题,如下图所示:

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String realPath=this.getServletContext().getRealPath("/src/日向雏田.jpg");
		String fileName=realPath.substring(realPath.lastIndexOf('\')+1);
		response.setHeader("content-disposition", "attachment;filename="+fileName);
		InputStream is=new FileInputStream(new File(realPath));
		OutputStream os=response.getOutputStream();
		byte[] buff=new byte[1024];
		int len=0;
		while((len=is.read(buff))>0){
			os.write(buff, 0, len);
		}
		os.close();
		is.close();
	}

  采用火狐浏览器进行测试,查看页面效果,及其响应结果如下:

  

  经过查看响应头分析,下载文件名存放在响应头中,且对于中文文字没有采用UTF-8、UTF-16、GBK等等能识别中文的编码,那么对于中文文件名导致采用哪种编码方式呢?查看REF 7578得知,在此处采用ASCII编码,但是REF规定,如果不可避免的要使用非ASCII码的字符,程序员应该均匀的使用UTF-8,来最小化交互操作的问题。

  所以,解决方案就是把文件名编码成UTF-8,传递给响应头,浏览器(部分)默认对该文件名进行UTF-8解码处理。

public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String realPath=this.getServletContext().getRealPath("/src/日向雏田.jpg");
		String fileName=realPath.substring(realPath.lastIndexOf('\')+1);
		String utf_8Name=URLEncoder.encode(fileName,"utf-8");//解决方案
		response.setHeader("content-disposition", "attachment;filename="+utf_8Name);
		InputStream is=new FileInputStream(new File(realPath));
		OutputStream os=response.getOutputStream();
		byte[] buff=new byte[1024];
		int len=0;
		while((len=is.read(buff))>0){
			os.write(buff, 0, len);
		}
		os.close();
		is.close();
	}

  效果如下:其中火狐浏览器并没有对其解码

 

相关文章

java速学教程(入门到精通)
java速学教程(入门到精通)

java怎么学习?java怎么入门?java在哪学?java怎么学才快?不用担心,这里为大家提供了java速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

616

2026.02.13

微博网页版主页入口与登录指南_官方网页端快速访问方法
微博网页版主页入口与登录指南_官方网页端快速访问方法

本专题系统整理微博网页版官方入口及网页端登录方式,涵盖首页直达地址、账号登录流程与常见访问问题说明,帮助用户快速找到微博官网主页,实现便捷、安全的网页端登录与内容浏览体验。

194

2026.02.13

Flutter跨平台开发与状态管理实战
Flutter跨平台开发与状态管理实战

本专题围绕Flutter框架展开,系统讲解跨平台UI构建原理与状态管理方案。内容涵盖Widget生命周期、路由管理、Provider与Bloc状态管理模式、网络请求封装及性能优化技巧。通过实战项目演示,帮助开发者构建流畅、可维护的跨平台移动应用。

91

2026.02.13

TypeScript工程化开发与Vite构建优化实践
TypeScript工程化开发与Vite构建优化实践

本专题面向前端开发者,深入讲解 TypeScript 类型系统与大型项目结构设计方法,并结合 Vite 构建工具优化前端工程化流程。内容包括模块化设计、类型声明管理、代码分割、热更新原理以及构建性能调优。通过完整项目示例,帮助开发者提升代码可维护性与开发效率。

20

2026.02.13

Redis高可用架构与分布式缓存实战
Redis高可用架构与分布式缓存实战

本专题围绕 Redis 在高并发系统中的应用展开,系统讲解主从复制、哨兵机制、Cluster 集群模式及数据分片原理。内容涵盖缓存穿透与雪崩解决方案、分布式锁实现、热点数据优化及持久化策略。通过真实业务场景演示,帮助开发者构建高可用、可扩展的分布式缓存系统。

54

2026.02.13

c语言 数据类型
c语言 数据类型

本专题整合了c语言数据类型相关内容,阅读专题下面的文章了解更多详细内容。

29

2026.02.12

雨课堂网页版登录入口与使用指南_官方在线教学平台访问方法
雨课堂网页版登录入口与使用指南_官方在线教学平台访问方法

本专题系统整理雨课堂网页版官方入口及在线登录方式,涵盖账号登录流程、官方直连入口及平台访问方法说明,帮助师生用户快速进入雨课堂在线教学平台,实现便捷、高效的课程学习与教学管理体验。

15

2026.02.12

豆包AI网页版入口与智能创作指南_官方在线写作与图片生成使用方法
豆包AI网页版入口与智能创作指南_官方在线写作与图片生成使用方法

本专题汇总豆包AI官方网页版入口及在线使用方式,涵盖智能写作工具、图片生成体验入口和官网登录方法,帮助用户快速直达豆包AI平台,高效完成文本创作与AI生图任务,实现便捷智能创作体验。

598

2026.02.12

PostgreSQL性能优化与索引调优实战
PostgreSQL性能优化与索引调优实战

本专题面向后端开发与数据库工程师,深入讲解 PostgreSQL 查询优化原理与索引机制。内容包括执行计划分析、常见索引类型对比、慢查询优化策略、事务隔离级别以及高并发场景下的性能调优技巧。通过实战案例解析,帮助开发者提升数据库响应速度与系统稳定性。

56

2026.02.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 3.7万人学习

C# 教程
C# 教程

共94课时 | 9.8万人学习

Java 教程
Java 教程

共578课时 | 68.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号