java和jsp的中文乱码问题.docx
- 文档编号:7905156
- 上传时间:2023-01-27
- 格式:DOCX
- 页数:13
- 大小:187.93KB
java和jsp的中文乱码问题.docx
《java和jsp的中文乱码问题.docx》由会员分享,可在线阅读,更多相关《java和jsp的中文乱码问题.docx(13页珍藏版)》请在冰豆网上搜索。
java和jsp的中文乱码问题
Servlet中文乱码问题及解决方案剖析
分类:
【JavaWeb】2012-01-2823:
26258人阅读评论(0)收藏举报
一、常识了解
一、什么是字符集?
什么是编码?
字符(Character)是文字与符号的总称,包括文字、图形符号、数学符号等。
一组抽象字符的集合就是字符集(Charset)。
字符集常常和一种具体的语言文字对应起来,该文字中的所有字符或者大部分常用字符就构成了该文字的字符集,比如英文字符集。
一组有共同特征的字符也可以组成字符集,比如繁体汉字字符集、日文汉字字符集。
字符集的子集也是字符集。
计算机要处理各种字符,就需要将字符和二进制内码对应起来,这种对应关系就是字符编码(Encoding)。
制定编码首先要确定字符集,并将字符集内的字符排序,然后和二进制数字对应起来。
根据字符集内字符的多少,会确定用几个字节来编码。
每种编码都限定了一个明确的字符集合,叫做被编码过的字符集(CodedCharacterSet),这是字符集的另外一个含义。
通常所说的字符集大多是这个含义。
二、有哪些字符集?
ASCII:
AmericanStandardCodeforInformationInterchange,美国信息交换标准码。
目前计算机中用得最广泛的字符集及其编码,由美国国家标准局(ANSI)制定。
它已被国际标准化组织(ISO)定为国际标准,称为ISO646标准。
ASCII字符集由控制字符和图形字符组成。
在计算机的存储单元中,一个ASCII码值占一个字节(8个二进制位),其最高位(b7)用作奇偶校验位。
所谓奇偶校验,是指在代码传送过程中用来检验是否出现错误的一种方法,一般分奇校验和偶校验两种。
奇校验规定:
正确的代码一个字节中1的个数必须是奇数,若非奇数,则在最高位b7添1。
偶校验规定:
正确的代码一个字节中1的个数必须是偶数,若非偶数,则在最高位b7添1。
ISO8859-1:
ISO8859,全称ISO/IEC8859,是国际标准化组织(ISO)及国际电工委员会(IEC)联合制定的一系列8位字符集的标准,现时定义了15个字符集。
ASCII收录了空格及94个“可印刷字符”,足以给英语使用。
但是,其他使用拉丁字母的语言(主要是欧洲国家的语言),都有一定数量的变音字母,故可以使用ASCII及控制字符以外的区域来储存及表示。
除了使用拉丁字母的语言外,使用西里尔字母的东欧语言、希腊语、泰语、现代阿拉伯语、希伯来语等,都可以使用这个形式来储存及表示。
*ISO8859-1(Latin-1)-西欧语言
*ISO8859-2(Latin-2)-中欧语言
*ISO8859-3(Latin-3)-南欧语言。
世界语也可用此字符集显示。
*ISO8859-4(Latin-4)-北欧语言
*ISO8859-5(Cyrillic)-斯拉夫语言
*ISO8859-6(Arabic)-阿拉伯语
*ISO8859-7(Greek)-希腊语
*ISO8859-8(Hebrew)-希伯来语(视觉顺序)
*ISO8859-8-I-希伯来语(逻辑顺序)
*ISO8859-9(Latin-5或Turkish)-它把Latin-1的冰岛语字母换走,加入土耳其语字母。
*ISO8859-10(Latin-6或Nordic)-北日耳曼语支,用来代替Latin-4。
*ISO8859-11(Thai)-泰语,从泰国的TIS620标准字集演化而来。
*ISO8859-13(Latin-7或BalticRim)-波罗的语族
*ISO8859-14(Latin-8或Celtic)-凯尔特语族
*ISO8859-15(Latin-9)-西欧语言,加入Latin-1欠缺的法语及芬兰语重音字母,以及欧元符号。
*ISO8859-16(Latin-10)-东南欧语言。
主要供罗马尼亚语使用,并加入欧元符号。
很明显,iso8859-1编码表示的字符范围很窄,无法表示中文字符。
但是,由于是单字节编码,和计算机最基础的表示单位一致,所以很多时候,仍旧使用iso8859-1编码来表示。
而且在很多协议上,默认使用该编码。
UCS:
通用字符集(UniversalCharacterSet,UCS)是由ISO制定的ISO10646(或称ISO/IEC10646)标准所定义的字符编码方式,采用4字节编码。
UCS包含了已知语言的所有字符。
除了拉丁语、希腊语、斯拉夫语、希伯来语、阿拉伯语、亚美尼亚语、格鲁吉亚语,还包括中文、日文、韩文这样的象形文字,UCS还包括大量的图形、印刷、数学、科学符号。
*UCS-2:
与unicode的2byte编码基本一样。
*UCS-4:
4byte编码,目前是在UCS-2前加上2个全零的byte。
Unicode:
Unicode(统一码、万国码、单一码)是一种在计算机上使用的字符编码。
它是http:
//www.unicode.org制定的编码机制,要将全世界常用文字都函括进去。
它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。
1990年开始研发,1994年正式公布。
随着计算机工作能力的增强,Unicode也在面世以来的十多年里得到普及。
但自从unicode2.0开始,unicode采用了与ISO10646-1相同的字库和字码,ISO也承诺ISO10646将不会给超出0x10FFFF的UCS-4编码赋值,使得两者保持一致。
Unicode的编码方式与ISO10646的通用字符集(UniversalCharacterSet,UCS)概念相对应,目前的用于实用的Unicode版本对应于UCS-2,使用16位的编码空间。
也就是每个字符占用2个字节,基本满足各种语言的使用。
实际上目前版本的Unicode尚未填充满这16位编码,保留了大量空间作为特殊使用或将来扩展。
UTF:
Unicode的实现方式不同于编码方式。
一个字符的Unicode编码是确定的,但是在实际传输过程中,由于不同系统平台的设计不一定一致,以及出于节省空间的目的,对Unicode编码的实现方式有所不同。
Unicode的实现方式称为Unicode转换格式(UnicodeTranslationFormat,简称为UTF)。
*UTF-8:
8bit变长编码,对于大多数常用字符集(ASCII中0~127字符)它只使用单字节,而对其它常用字符(特别是朝鲜和汉语会意文字),它使用3字节。
*UTF-16:
16bit编码,是变长码,大致相当于20位编码,值在0到0x10FFFF之间,基本上就是unicode编码的实现,与CPU字序有关。
汉字编码:
*GB2312字集是简体字集,全称为GB2312(80)字集,共包括国标简体汉字6763个。
*BIG5字集是台湾繁体字集,共包括国标繁体汉字13053个。
*GBK字集是简繁字集,包括了GB字集、BIG5字集和一些符号,共包括21003个字符。
*GB18030是国家制定的一个强制性大字集标准,全称为GB18030-2000,它的推出使汉字集有了一个“大一统”的标准。
ANSI和Unicodebigendia:
我们在Windows系统中保存文本文件时通常可以选择编码为ANSI、Unicode、Unicodebigendian和UTF-8,这里的ANSI和Unicodebigendia是什么编码呢?
ANSI:
使用2个字节来代表一个字符的各种汉字延伸编码方式,称为ANSI编码。
在简体中文系统下,ANSI编码代表GB2312编码,在日文操作系统下,ANSI编码代表JIS编码。
Unicodebigendia:
UTF-8以字节为编码单元,没有字节序的问题。
UTF-16以两个字节为编码单元,在解释一个UTF-16文本前,首先要弄清楚每个编码单元的字节序。
Unicode规范中推荐的标记字节顺序的方法是BOM(即ByteOrderMark)。
在UCS编码中有一个叫做"ZEROWIDTHNO-BREAKSPACE"的字符,它的编码是FEFF。
而FFFE在UCS中是不存在的字符,所以不应该出现在实际传输中。
UCS规范建议我们在传输字节流前,先传输字符"ZEROWIDTHNO-BREAKSPACE"。
这样如果接收者收到FEFF,就表明这个字节流是Big-Endian的;如果收到FFFE,就表明这个字节流是Little-Endian的。
因此字符"ZEROWIDTHNO-BREAKSPACE"又被称作BOM。
Windows就是使用BOM来标记文本文件的编码方式的。
三、编程语言与编码
C、C++、Python2内部字符串都是使用当前系统默认编码
Python3、Java内部字符串用Unicode保存
Ruby有一个内部变量$KCODE用来表示可识别的多字节字符串的编码,变量值为"EUC""SJIS""UTF8""NONE"之一。
$KCODE的值为"EUC"时,将假定字符串或正则表达式的编码为EUC-JP。
同样地,若为"SJIS"时则认定为ShiftJIS。
若为"UTF8"时则认定为UTF-8。
若为"NONE"时,将不会识别多字节字符串。
在向该变量赋值时,只有第1个字节起作用,且不区分大小写字母。
"e""E"代表"EUC","s""S"代表"SJIS","u""U"代表"UTF8",而"n""N"则代表"NONE"。
默认值为"NONE"。
即默认情况下Ruby把字符串当成单字节序列来处理。
四、为什么会乱码?
乱码是个老问题,从上面我们知道,字符在保存时的编码格式如果和要显示的编码格式不一样的话,就会出现乱码问题。
我们的Web系统,从底层数据库编码、Web应用程序编码到HTML页面编码,如果有一项不一致的话,就会出现乱码。
所以,解决乱码问题说难也难说简单也简单,关键是让交互系统之间编码一致。
五、有没有万金油?
在如此多种编码和字符集弄的我们眼花缭乱的情况下,我们只需选择一种兼容性最好的编码方式和字符集,让它成为我们程序子系统之间
交互的编码契约,那么从此恼人的乱码问题即将远离我们而去--这种兼容性最好的编码就是UTF-8!
毕竟GBK/GB2312是国内的标准,当我们大量使用国外的开源软件时,UTF-8才是编码界最通用的语言。
1.GBK包含GB2312,即如果通过GB2312编码后可以通过GBK解码,反之可能不成立;
2.java.nio.charset.Charset.defaultCharset() 获得平台默认字符编码;
3.getBytes()是通过平台默认字符集进行编码;
二、中文乱码出现
在学习任何一门技术时,经常会有初学者遇到中文乱码问题,比如MySQL,是因为在安装时没有设置;而在Servlet中,也会遇到中文乱码问题;
比如:
OutputStreamout=response.getOutputStream();
out.write(String);
输出中文时可能会出现乱码;
比如:
[java]viewplaincopyprint?
1.protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
2.
3. OutputStream out = response.getOutputStream();
4. String data = "博客";
5. out.write(data.getBytes("UTF-8"));
6. }
输出乱码的问题是程序用UTF-8编码,而浏览器用GB2312解码,因此会出现乱码;
Servlet乱码分为request乱码和response乱码;
三、response中文乱码
在网上很有效的解决方法是添加:
response.setCharacterEncoding("UTF-8");
解决不了,后来又搜到一条解决方法是:
respnse.setHeader("content-type","text/html;charset=UTF-8");
两句都填上,后来终于解决了这个问题;
其实我们应该思考一下本质;
问题1:
我们这里先来说明一下错误的原因,下图是显示乱码的流程图:
response.setContentType("text/html;charset=UTF-8");目的是为了控制浏览器的行为,即控制浏览器用UTF-8进行解码;
response.setCharacterEncoding("UTF-8");的目的是用于response.getWriter()输出的字符流的乱码问题,如果是response.getOutputStream()是不需要此种解决方案的;因为这句话的意思是为了将response对象中的数据以UTF-8解码后发向浏览器;
解决方案流程图:
问题2
问题代码如下:
[java]viewplaincopyprint?
1.protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
2. PrintWriter out = response.getWriter();
3. String data = "博客";
4. out.println(data);
5. }
浏览器输出:
?
?
原因:
"博客"首先被封装在response对象中,因为IE和WEB服务器之间不能传输文本,然后就通过ISO-8859-1进行编码,但是ISO-8859-1中没有“博客”的编码,因此输出“?
?
”表示没有编码;
错误代码流程图:
而解决方案是:
response.setCharacterEncoding("GB2312");设置response使用的码表
解决方案流程图:
补充:
通过标签模拟response头;
四、request乱码问题
request请求分为post和get,对于不同的请求方式有不同的解决乱码的方案;
1.post请求乱码
错误原因:
解决方案:
2.get请求乱码
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- java jsp 中文 乱码 问题