当前位置:网站首页 >> 养生

JSP-Servlet 中的汉字编码问题_0_a

时间:2020-01-17 00:16:25 来源:互联网 阅读:0次

网上就 JSP/Servlet 中 DBCS 字符编码问题有许多的文章和讨论,本文对它们作一些整理,并结合 IBM WebSphere Application Server 3.5(WAS)的解决方法作一些说明,希望它不是多余的。

内容:

问题的起源

GB2312-80,GBK,GB18030-2000 汉字字符集及 Encoding

中文转码时'?'、乱码的由来

JSP/Servlet 汉字编码问题及在 WAS 中的解决办法

结束语

1. 问题的起源

每个国家(或区域)都规定了计算机信息交换用的字符编码集,如美国的扩展 ASCII码, 中国的 GB2312-80,日本的 JIS 等,作为该国家/区域内信息处理的基础,有着统一编码的重要作用。字符编码集按长度分为 SBCS(单字节字符集),DBCS(双字节字符集)两大类。早期的软件(尤其是操作系统),为了解决本地字符信息的计算机处理,出现了各种本地化版本(L10N),为了区分,引进了 LANG, Codepage 等概念。但是由于各个本地字符集代码范围重叠,相互间信息交换困难;软件各个本地化版本独立维护成本较高。因此有必要将本地化工作中的共性抽取出来,作一致处理,将特别的本地化处理内容降低到少。这也就是所谓的国际化(I18N)。各种语言信息被进一步规范为 Locale 信息。处理的底层字符集变成了几乎包含了所有字形的 Unicode。

现在大部分具有国际化特征的软件核心字符处理都是以 Unicode 为基础的,在软件运行时根据当时的 Locale/Lang/Codepage 设置确定相应的本地字符编码设置,并依此处理本地字符。在处理过程中需要实现 Unicode 和本地字符集的相互转换,甚或以 Unicode 为中间的两个不同本地字符集的相互转换。这种方式在网络环境下被进一步延伸,任何网络两端的字符信息也需要根据字符集的设置转换成可接受的内容。

Java 语言内部是用 Unicode 表示字符的,遵守 Unicode V2.0。Java 程序无论是从/往文件系统以字符流读/写文件,还是往 URL 连接写 HTML 信息,或从 URL 连接读取参数值,都会有字符编码的转换。这样做虽然增加了编程的复杂度,容易引起混淆,但却是符合国际化的思想的。

从理论上来说,这些根据字符集设置而进行的字符转换不应该产生太多问题。而事实是由于应用程序的实际运行环境不同,Unicode 和各个本地字符集的补充、完善,以及系统或应用程序实现的不规范,转码时出现的问题时时困扰着程序员和用户。

2. GB2312-80,GBK,GB18030-2000 汉字字符集及 Encoding

其实解决 JAVA 程序中的汉字编码问题的方法往往很简单,但理解其背后的原因,定位问题,还需要了解现有的汉字编码和编码转换。

GB2312-80 是在国内计算机汉字信息技术发展初始阶段制定的,其中包含了大部分常用的一、二级汉字,和 9 区的符号。该字符集是几乎所有的中文系统和国际化的软件都支持的中文字符集,这也是基本的中文字符集。其编码范围是高位0xa1-0xfe,低位也是 0xa1-0xfe;汉字从 0xb0a1 开始,结束于 0xf7fe;

GBK 是 GB2312-80 的扩展,是向上兼容的。它包含了 20902 个汉字,其编码范围是 0x8140-0xfefe,剔除高位 0x80 的字位。其所有字符都可以一对一映射到 Unicode 2.0,也就是说 JAVA 实际上提供了 GBK 字符集的支持。这是现阶段 Windows 和其它一些中文操作系统的缺省字符集,但并不是所有的国际化软件都支持该字符集,感觉是他们并不完全知道 GBK 是怎么回事。值得注意的是它不是国家标准,而只是规范。随着 GB18030-2000国标的发布,它将在不久的将来完成它的历史使命。

GB18030-2000(GBK2K) 在 GBK 的基础上进一步扩展了汉字,增加了藏、蒙等少数民族的字形。GBK2K 从根本上解决了字位不够,字形不足的问题。它有几个特点,

它并没有确定所有的字形,只是规定了编码范围,留待以后扩充。

编码是变长的,其二字节部分与 GBK 兼容;四字节部分是扩充的字形、字位,其编码范围是首字节 0x81-0xfe、二字节0x30-0x39、三字节 0x81-0xfe、四字节0x30-0x39。

它的推广是分阶段的,首先要求实现的是能够完全映射到 Unicode 3.0 标准的所有字形。

它是国家标准,是强制性的。

现在还没有任何一个操作系统或软件实现了 GBK2K 的支持,这是现阶段和将来汉化的工作内容。

Unicode 的介绍......就免了吧。

JAVA 支持的encoding中与中文编程相关的有:(有几个在JDK文档中未列出) ASCII 7-bit, 同 ascii7

ISO8859-1 8-bit, 同 8859_1,ISO-8859-1,ISO_8859-1,latin1...

GB2312-80 同gb2312,gb2312-1980,EUC_CN,euccn,1381,Cp1381, 1383, Cp1383, ISO2022CN,ISO2022CN_GB......

GBK (注意大小写),同MS936

UTF8 UTF-8

GB18030 (现在只有IBM JDK1.3.?有支持), 同Cp1392,1392

JAVA 语言采用Unicode处理字符. 但从另一个角度来说,在java程序中也可以采用非Unicode的转码,重要的是保证程序入口和出口的汉字信息不失真。如完全采用ISO-8859-1来处理汉字也能达到正确的结果。网络上流行的许多解决方法,都属于这种类型。为了不致引起混淆,本文不对这种方法作讨论。

3. 中文转码时'?'、乱码的由来

两个方向转换都有可能得到错误的结果:

Unicode-->Byte, 如果目标代码集不存在对应的代码,则得到的结果是0x3f.

如:

"\u00d6\u00ec\u00e9\u0046\u00bb\u00f9".getBytes("GBK") 的结果是 "?ìéF?ù", Hex 值是3fa8aca8a6463fa8b4.

仔细看一下上面的结果,你会发现\u00ec被转换为0xa8ac, \u00e9被转换为\xa8a6... 它的实际有效位变长了! 这是因为GB2312符号区中的一些符号被映射到一些公共的符号编码,由于这些符号出现在ISO-8859-1或其它一些SBCS字符集中,故它们在Unicode中编码比较靠前,有一些其有效位只有8位,和汉字的编码重叠(其实这种映射只是编码的映射,在显示时仔细不是一样的。Unicode 中的符号是单字节宽,汉字中的符号是双字节宽) . 在Unicode\u00a0--\u00ff 之间这样的符号有20个。了解这个特征非常重要!由此就不难理解为什么JAVA编程中,汉字编码的错误结果中常常会出现一些乱码(其实是符号字符), 而不全是'?'字符, 就比如上面的例子。

Byte-->Unicode, 如果Byte标识的字符在源代码集不存在,则得到的结果是0xfffd.

如:

Byte ba[] = {(byte)0x81,(byte)0x40,(byte)0xb0,(byte)0xa1}; new String(ba,"gb2312");

结果是"?啊", hex 值是"\ufffd\u554a". 0x8140 是GBK字符,按GB2312转换表没有对应的值,取\ufffd. (请注意:在显示该uniCode时,因为没有对应的本地字符,所以也适用上一种情况,显示为一个"?".)

实际编程中,JSP/Servlet 程序得到错误的汉字信息,往往是这两个过程的叠加,有时甚至是两个过程叠加后反复作用的结果.

4. JSP/Servlet 汉字编码问题及在 WAS 中的解决办法

4.1 常见的 encoding 问题的现象

网上常出现的 JSP/Servlet encoding 问题一般都表现在 browser 或应用程序端,如:

浏览器中看到的 Jsp/Servlet 页面中的汉字怎么都成了 ’?’ ?

浏览器中看到的 Servlet 页面中的汉字怎么都成了乱码?

JAVA 应用程序界面中的汉字怎么都成了方块?

Jsp/Servlet 页面无法显示 GBK 汉字。

JSP 页面中内嵌在,等Tag包含的 JAVA code 中的中文成了乱码,但页面的其它汉字是对的。

Jsp/Servlet 不能接收 form 提交的汉字。

JSP/Servlet 数据库读写无法获得正确的内容。

隐藏在这些问题后面的是各种错误的字符转换和处理(除第3个外,是因为 Java font 设置错误引起的)。解决类似的字符 encoding 问题,需要了解 Jsp/Servlet 的运行过程,检查可能出现问题的各个点。

4.2 JSP/Servlet web 编程时的 encoding 问题

运行于Java 应用服务器的 JSP/Servlet 为 Browser 提供 HTML 内容,其过程如下图所示:

其中有字符编码转换的地方有:

JSP 编译。Java 应用服务器将根据 JVM 的 file.encoding 值读取 JSP 源文件,编译生成 JAVA 源文件,再根据 file.encoding 值写回文件系统。如果当前系统语言支持 GBK,那么这时候不会出现 encoding 问题。如果是英文的系统,如 LANG 是 en_US 的 Linux, AIX 或 Solaris,则要将 JVM 的 file.encoding 值置成 GBK 。系统语言如果是 GB2312,则根据需要,确定要不要设置 file.encoding,将 file.encoding 设为 GBK 可以解决潜在的 GBK 字符乱码问题

Java 需要被编译为 .class 才能在 JVM 中执行,这个过程存在与a.同样的 file.encoding 问题。从这里开始 servlet 和 jsp 的运行就类似了,只不过 Servlet 的编译不是自动进行的。对于JSP程序, 对产生的JAVA 中间文件的编译是自动进行的(在程序中直接调用sun.tools.javac.Main类). 因此如果在这一步出现问题的话, 也要检查encoding和OS的语言环境,或者将内嵌在JSP JAVA Code 中的静态汉字转为 Unicode, 要么静态文本输出不要放在 JAVA code 中。 对于Servlet, javac 编译时手工指定-encoding 参数就可以了。

Servlet 需要将 HTML 页面内容转换为 browser 可接受的 encoding 内容发送出去。依赖于各 JAVA App Server 的实现方式,有的将查询 Browser 的 accept-charset 和 accept-language 参数或以其它猜的方式确定 encoding 值,有的则不管。因此采用固定encoding 也许是的解决方法。查看本文来源

希爱力治疗术后ED怎么样
适合小孩子用法用量明确的药哪个好
消肿止痛的有哪些中药
关于儿童用法用量明确止咳药

相关文章

一周热门

热点排行

热门精选

友情链接: 武威法四医院哪家好 张掖放疗科医院哪家好 张掖碎石中心医院哪家好 平凉老年病科医院哪家好 平凉体检科医院哪家好 酒泉康复医学科医院哪家好 酒泉普通内科医院哪家好 酒泉小儿消化科医院哪家好 酒泉种植科医院哪家好 庆阳产科医院哪家好 庆阳过敏反应科医院哪家好 庆阳小儿耳鼻喉医院哪家好 庆阳胸外科医院哪家好 定西地方病科医院哪家好 定西中医呼吸科医院哪家好 定西放射科医院哪家好 林芝耳鼻咽喉头颈科医院哪家好 林芝麻醉医学科医院哪家好 图木舒克小儿眼科医院哪家好 图木舒克检验科医院哪家好 海口微创外科医院哪家好 海口中医肛肠科医院哪家好 三亚康复医学科医院哪家好 三亚职业病科医院哪家好 三亚中西医结合科医院哪家好 三亚神经内科医院哪家好 三亚血液科医院哪家好 三亚小儿外科医院哪家好 三亚综合医院哪家好 五指山中西医结合科医院哪家好 五指山小儿妇科医院哪家好 五指山小儿神经外科医院哪家好 五指山小儿眼科医院哪家好 五指山计划生育科医院哪家好 五指山口腔修复科医院哪家好 五指山口腔粘膜科医院哪家好 儋州放疗科医院哪家好 儋州神经内科医院哪家好 儋州肾病内科医院哪家好 白沙肿瘤康复科医院哪家好 昌江外伤科医院哪家好 海南屈光医院哪家好 海南青光眼医院哪家好 果洛其他内科医院哪家好 果洛检验科医院哪家好 果洛干部诊疗科医院哪家好 果洛动脉导管未闭医院哪家好 玉树产科医院哪家好 大理一乙医院哪家好 孕期防辐射 牙龈炎预防 后牙反合 插入技巧 新婚避孕 石榴 刷牙的正确方法 护手霜 早孕试纸怎么用 怀孕初期吃什么好 如何缓解压力 亲子瑜伽 不孕不育如何预防 风湿病能吃的食物 更年期综合症的治疗 脑瘫保健护理 脑血栓发病原因 帕金森如何治疗 外阴疾病发病原因 不孕不育治疗哪里好 男性炎症性不育的表现 如何检查风湿病 如何检查皮炎 白癜风如何治愈 白癜风饮食注意事项 不孕不育的病因有那些 癫痫饮食注意事项 动脉硬化吃什么 儿童齿科吃什么 儿童口腔科 肺癌饮食注意事项 假体隆鼻整形医院 山东管瘤医院 胃溃疡怎么办 银屑病的病因有那些 治疗儿童癫痫的方法 宜宾癫痫病医院 鹰潭癫痫病医院 平顶山白癜风医院 阳泉白癜风医院 张家界白癜风医院 潜江耳鼻咽喉头颈科医院哪家好 抚州有哪些医院 抚州有哪些医院 四平有哪些医院 潜江心血管内科医院哪家好 白山有哪些医院 来宾有哪些医院 潜江急诊科医院哪家好 潜江检验科医院哪家好 普洱有哪些医院
媒体合作:

Copyright (c) 2011 八零CMS 版权所有 备案号:苏ICP备17012668号-2

网站地图