java中文乱码问题产生原因分析

上传人:第*** 文档编号:30972641 上传时间:2018-02-03 格式:DOC 页数:8 大小:93.50KB
返回 下载 相关 举报
java中文乱码问题产生原因分析_第1页
第1页 / 共8页
java中文乱码问题产生原因分析_第2页
第2页 / 共8页
java中文乱码问题产生原因分析_第3页
第3页 / 共8页
java中文乱码问题产生原因分析_第4页
第4页 / 共8页
java中文乱码问题产生原因分析_第5页
第5页 / 共8页
点击查看更多>>
资源描述

《java中文乱码问题产生原因分析》由会员分享,可在线阅读,更多相关《java中文乱码问题产生原因分析(8页珍藏版)》请在金锄头文库上搜索。

1、Java 中文乱码问题产生原因分析在计算机中,只有二进制的数据,不管数据是在内存中,还是在外部存储设备上。对于我们所看到的字符,也是以二进制数据的形式存在的。不同字符对应二进制数的规则,就是字符的编码。字符编码的集合称为字符集。17.1.1 常用字符集在早期的计算机系统中,使用的字符非常少,这些字符包括 26 个英文字母、数字符号和一些常用符号(包括控制符号) ,对这些字符进行编码,用 1 个字节就足够了(1 个字节可以表示 28=256 种字符) 。然而实际上,表示这些字符,只使用了 1 个字节的 7 位,这就是 ASCII 编码。1ASCIIASCII(American Standard

2、Code for Information Interchange,美国信息互换标准代码) ,是基于常用的英文字符的一套电脑编码系统。每一个 ASCII 码与一个 8 位(bit)二进制数对应。其最高位是 0,相应的十进制数是 0127。例如,数字字符“0”的编码用十进制数表示就是 48。另有 128 个扩展的 ASCII码,最高位都是 1,由一些图形和画线符号组成。ASCII 是现今最通用的单字节编码系统。ASCII 用一个字节来表示字符,最多能够表示 256 种字符。随着计算机的普及,许多国家都将本地的语言符号引入到计算机中,扩展了计算机中字符的范围,于是就出现了各种不同的字符集。2ISO8

3、859-1因为 ASCII 码中缺少、 和许多书写其他语言所需的字符,为此,可以通过指定 128 以后的字符来扩展 ASCII 码。国际标准组织( ISO)定义了几个不同的字符集,它们是在 ASCII 码基础上增加了其他语言和地区需要的字符。其中最常用的是 ISO8859-1,通常叫做 Latin-1。Latin-1 包括了书写所有西方欧洲语言不可缺少的附加字符,其中 0127 的字符与 ASCII 码相同。ISO 8859 另外定义了 14 个适用于不同文字的字符集(8859-2 到 8859-15) 。这些字符集共享 0 127 的 ASCII 码,只是每个字符集都包含了128255 的其

4、他字符。3GB2312 和 GBK GB2312 是中华人民共和国国家标准汉字信息交换用编码,全称信息交换用汉字编码字符集基本集 ,标准号为 GB2312-80,是一个由中华人民共和国国家标准总局发布的关于简化汉字的编码,通行于中国大陆和新加坡,简称国标码。因为中文字符数量较多,所以采用两个字节来表示一个字符,分别称为高位和低位。为了和 ASCII码有所区别,中文字符的每一个字节的最高位都用 1 来表示。GB2312 字符集是几乎所有的中文系统和国际化的软件都支持的中文字符集,也是最基本的中文字符集。它包含了大部分常用的一、二级汉字和 9区的符号,其编码范围是高位 0xa1-0xfe,低位也是

5、 0xa1-0xfe,汉字从 0xb0a1 开始,结束于 0xf 7fe。为了对更多的字符和符号进行编码,由前电子部科技质量司和国家技术监督局标准化司于 1995 年 12月颁布了 GBK(K 是“扩展”的汉语拼音第一个字母)编码规范,在新的编码系统里,除了完全兼容GB2312 外,还对繁体中文、一些不常用的汉字和许多符号进行了编码。它也是现阶段 Windows 和其他一些中文操作系统的默认字符集,但并不是所有的国际化软件都支持该字符集。不过要注意的是 GBK 不是国家标准,它只是规范。GBK 字符集包含了 20 902 个汉字,其编码范围是 0x8140-0xfefe。每个国家(或区域)都规

6、定了计算机信息交换用的字符编码集,这就造成了交流上的困难。想像一下,你发送一封中文邮件给一位远在西班牙的朋友,当邮件通过网络发送出去的时候,你所书写的中文字符会按照本地的字符集 GBK 转换为二进制编码数据,然后发送出去。当你的朋友接收到邮件(二进制数据)后,查看信件时,会按照他所用系统的字符集,将二进制编码数据解码为字符,然而由于两种字符集之间编码的规则不同,导致转换出现乱码。这是因为,在不同的字符集之间,同样的数字可能对应了不同的符号,也可能在另一种字符集中,该数字没有对应符号。为了解决上述问题,统一全世界的字符编码,由 Unicode 协会 1制定并发布了 Unicode 编码。4Uni

7、codeUnicode(统一的字符编码标准集)使用 065 535 的双字节无符号数对每一个字符进行编码。它不仅包含来自英语和其他西欧国家字母表中的常见字母和符号,也包含来自古斯拉夫语、希腊语、希伯来语、阿拉伯语和梵语的字母表。另外还包含汉语和日语的象形汉字和韩国的 Hangul 音节表。目前已经定义了 40 000 多个不同的 Unicode 字符,剩余 25 000 个空缺留给将来扩展使用。其中大约1 Unicode 协会是由 IBM、微软、Adobe、SUN、加州大学伯克利分校等公司和组织所组成的非营利性组织。20 000 个字符用于汉字,另外 11 000 左右的字符用于韩语音节。Un

8、icode 中 0255 的字符与 ISO8859-1中的一致。Unicode 编码对于英文字符采取前面加“0”字节的策略实现等长兼容。如 “a”的 ASCII 码为0x61,Unicode 码就为 0x00,0x61。5UTF-8使用 Unicode 编码,一个英文字符要占用两个字节,在 Internet 上,大多数的信息都是用英文来表示的,如果都采用 Unicode 编码,将会使数据量增加一倍。为了减少存储和传输英文字符数据的数据量,可以使用 UTF-8 编码。UTF-8 全称是 Eight-bit UCS Transformation Format(UCS,Universal Chara

9、cter Set,通用字符集,UCS 是所有其他字符集标准的一个超集) 。对于常用的字符,即 0127 的 ASCII 字符,UTF-8 用一个字节 来 表 示 , 这 意 味 着 只 包 含 7 位 ASCII 字 符 的 字 符 数 据 在 ASCII 和 UTF-8 两 种 编 码 方 式 下 是 一 样 的。如果字符对应的 Unicode 码是 0x0000,或在 0x0080 与 0x007f 之间,对应的 UTF-8 编码是两个字节,如果字符对应的 Unicode 码在 0x0800 与 0xffff 之间,对应的 UTF-8 编码是三个字节。因为中文字符的 Unicode编码在

10、0x0800 与 0xffff 之间,所以数据如果是中文,采用 UTF-8 编码数据量会增加 50%。Unicode 与 UTF-8 转换的规则简述如下:(1)如果 Unicode 编码的 16 位二进制数的前 9 位是 0,则 UTF-8 编码用 1 个字节来表示,这个字节的首位是“0” ,剩下的 7 位与原二进制数据的后 7 位相同。例如:Unicode 编码:u0061 = 00000000 01100001UTF-8 编码:01100001 = 0x61(2)如果 Unicode 编码的 16 位二进制数的头 5 位是 0,则 UTF-8 编码用 2 个字节来表示,首字节以“110”开

11、头,后面的 5 位与原二进制数据除去前 5 个零后的最高 5 位相同;第二个字节以“10”开头,后面的 6 位与原二进制数据中的低 6 位相同。例如:Unicode 编码:u00A9 = 00000000 10101001UTF-8 编码:11000010 10101001 = 0xC2 0xA9(3)如果不符合上述两个规则,则用三个字节表示。第一个字节以“1110”开头,后四位为原二进制数据的高四位;第二个字节以“10”开头,后六位为原二进制数据中间的六位;第三个字节以“10”开头,后六位为原二进制数据的低六位。例如:Unicode 编码:u4E2D = 01001110 00101101U

12、TF-8 编码:11100100 10111000 10101101 = 0xE4 0xB8 0xAD在 UTF-8 编码的多字节串中,第一个字节开头 “1”的数目就是整个字符串中字节的数目。17.1.2 对乱码产生过程的分析为了让使用 Java 语言编写的程序能在各种语言的平台下运行, Java 在其内部使用 Unicode 字符集来表示字符,这样就存在 Unicode 字符集和本地字符集进行转换的过程。当在 Java 中读取字符数据的时候 ,需 要 将 本 地 字 符 集 编 码 的 数 据 转 换 为 Unicode 编 码 , 而 在 输 出 字 符 数 据 的 时 候 , 则 需 要

13、 将 Unicode 编码转换为本地字符集编码。例如,在中文系统下,从控制台读取一个字符“中” ,实际上读取的是“中”的 GBK 编码 0xD6D0,在 Java 语言中要将 GBK 编码转换为 Unicode 编码 0x4E2D,此时,在内存中,字符“中”对应的数值就是 0x4E2D,当我们向控制台输出字符时, Java 语言将 Unicode 编码再转换为 GBK 编码,输出到控制台,中文系统再根据 GBK 字符集画出相应的字符。从上述过程来看,读取和写入的过程是可逆的,那么理应不会出现中文乱码问题。然而,实际应用的情形,比上述过程要复杂得多。在 Web 应用中,通常都包括了浏览器、 We

14、b 服务器、Web 应用程序和数据库等部分,每一部分都有可能使用不同的字符集,从而导致字符数据在各种不同的字符集之间转换时,出现乱码的问题。在 Java 语言中,不同字符集编码的转换,都是通过 Unicode 编码作为中介来完成的。例如,GBK 编码的字符“中”要转换为 ISO-8859-1(同 ISO8859-1)编码,其过程如下:(1)因为在 Java 中的字符,都是用 Unicode 来表示的,所以 GBK 编码的字符“中”要转换为Unicode 表示:0xD6D0-0x4E2D。(2)将字符“中”的 Unicode 编码转换为 ISO-8859-1 编码,因为 Unicode 编码 0

15、x4E2D 在 ISO-8859-1 中没有对应的编码,于是得到 0x3f,也就是字符“ ?”。下面的代码演示了这一过程:/GBK 编码的字符“中”转换为 Unicode 编码表示String str=中;/将字符 “中”的 Unicode 编码转换为 ISO-8859-1 编码byte b=str.getBytes(ISO-8859-1);for(int i=0;i为了指定输出内容的编码格式,设置 page 指令 contentType 属性,如下:在 Web 容器转换 JSP 页面后的 Servlet 类中,会自动添加下面的代码:response.setContentType(text/h

16、tml; charset=GBK);2以 GET 方法提交的表单数据中有中文字符当提交表单采用 GET 方法时,提交的数据作为查询字符串被附加到 URL 的末端,发送到服务器,此时在服务器端调用 setCharacterEncoding()方法也就没有作用了。我们需要在得到请求参数的值后,自己做正确的编码转换。String name = request.getParameter(name);name=new String(name.getBytes(ISO-8859-1),GBK);在第一行,调用 getParameter()方法得到的字符串 name 的 Unicode 值是以 ISO-8859-1 编码转换而来,调用 name.getBytes(ISO-8859-1 ) ,将得到原始的 GBK 编码值,接着,对 new String()的调用将以 GBK字符集重新构造字符串的 Unicode 编码。为了方便从 ISO-8859-1 编码到 GBK 的转换,我们

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 建筑/环境 > 工程造价

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号