当前位置:文档之家› Java 编程技术中汉字问题

Java 编程技术中汉字问题

Java 编程技术中汉字问题
Java 编程技术中汉字问题

中文编码的处理

每个国家(或区域)都规定了计算机信息交换用的字符编码集,如美国的扩展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

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

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

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

国标的发布,它将在不久的将来完成它的历史使命。

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

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

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

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

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

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

JA V A 支持的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

JA V A 语言采用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个。了解这个特征非常重要!由此就不难理解为什么JA V A编程中,汉字编码的错误结果中常常会出现一些乱码(其实是符号字符), 而不

全是'?'字符, 就比如上面的例子。

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 汉字编码问题及在W AS 中的解决办法

4.1 常见的encoding 问题的现象

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

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

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

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

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

JSP 页面中内嵌在<%...%>,<%=...%>等Tag包含的JA V A 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 源文件,编译生成JA V A 源文件,再根据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程序, 对产生的JA V A 中间文件的编译是自动进行的(在程序中直接调用

sun.tools.javac.Main类). 因此如果在这一步出现问题的话, 也要检查encoding和OS的语言环境,或者将内嵌在JSP JA V A Code 中的静态汉字转为Unicode, 要么静态文本输出不要放在JA V A code 中。对于Servlet, javac 编译时手工指定-encoding 参数就可以了。

Servlet 需要将HTML 页面内容转换为browser 可接受的encoding 内容发送出去。依赖于各JA V A App Server 的实现方式,有的将查询Browser 的accept-charset 和accept-language 参数或以其它猜的方式确定encoding 值,有的则不管。因此采用固定encoding 也许是最好的解决方法。对于中文网页,可在JSP 或Servlet 中设置contentType="text/html; charset=GB2312";如果页面中有GBK字符,则设置为contentType="text/html; charset=GBK",由于IE 和Netscape对GBK的支持程度不一样,作这种设置时需要测试一下。

因为16位JA V A char在网络传送时高8位会被丢弃,也为了确保Servlet页面中的汉字(包括内嵌的和servlet运行过程中得到的)是期望的内码,可以用PrintWriter out=res.getWriter() 取代ServletOutputStream out=res.getOutputStream(). PrinterWriter 将根据contentType中指定的charset作转换(ContentType需在此之前指定!); 也可以用OutputStreamWriter封装ServletOutputStream 类并用write(String)输出汉字字符串。

对于JSP,JA V A Application Server 应当能够确保在这个阶段将嵌入的汉字正确传送出去。

这是解释URL 字符encoding 问题。如果通过get/post 方式从browser 返回的参数值中包含汉字信息,servlet 将无法得到正确的值。SUN的J2SDK 中,HttpUtils.parseName 在解析参数时根本没有考虑browser 的语言设置,而是将得到的值按byte 方式解析。这是网上讨论得最多的encoding 问题。因为这是设计缺陷,只能以bin 方式重新解析得到的字符串;或者以hack HttpUtils 类的方式解决。参考文章 2 均有介绍,不过最好将其中的中文encoding GB2312、CP1381 都改为GBK,否则遇到GBK 汉字时,还是会有问题。Servlet API 2.3 提供一个新的函数HttpServeletRequest.setCharacterEncoding 用于在调用request.getParameter(“param_name”) 前指定应用程序希望的encoding,这将有助于彻底解决这个问题。

4.3 IBM Websphere Application Server 中的解决方法

WebSphere Application Server 对标准的Servlet API 2.x 作了扩展,提供较好的多语言支持。运行在中文的操作系统中,可以不作任何设置就可以很好地处理汉字。下面的说明只是对WAS是运行在英文的系统中,或者需要有GBK支持时有效。

上述c,d情况,W AS 都要查询Browser 的语言设置,在缺省状况下,zh, zh-cn 等均被映射为JA V A encoding CP1381(注意:CP1381 只是等同于GB2312 的一个codepage,没有GBK 支持)。这样做我想是因为无法确认Browser 运行的操作系统是支持GB2312, 还是GBK,所以取其小。但是实际的应用系统还是要求页面中出现GBK 汉字,最著名的是朱总理名字中的“镕"(rong2 ,0xe946,\u9555),所以有时还是需要将Encoding/Charset 指定为GBK。当然WAS 中变更缺省的encoding 没有上面说的那么麻烦,针对a,b,参考文章5,在Application Server 的命令行参数中指定-Dfile.encoding=GBK 即可;针对d,在Application Server 的命令行参数中指定-Ddefault.client.encoding=GBK。如果指定了-Ddefault.client.encoding= GBK,那么c情况下可以不再指定charset。

上面列出的问题中还有一个关于Tag<%...%>,<%=...%>中的JA V A 代码里包含的静态文本未能正确显示的问题,在WAS中的解决方法是除了设置正确的file.encoding, 还需要以相同方法设置https://www.doczj.com/doc/273822466.html,nguage=zh -Duser.region=CN。这与JA V A locale的设置有关。

4.4 数据库读写时的encoding 问题

JSP/Servlet 编程中经常出现encoding 问题的另一个地方是读写数据库中的数据。

流行的关系数据库系统都支持数据库encoding,也就是说在创建数据库时可以指定它自己的字符集设置,数据库的数据以指定的编码形式存储。当应用程序访问数据时,在入口和出口处都会有encoding 转换。对于中文数据,数据库字符编码的设置应当保证数据的完整性. GB2312,GBK,UTF-8 等都是可选的数据库encoding;也可以选择ISO8859-1 (8-bit),那么应用程序在写数据之前须将16Bit 的一个汉字或Unicode 拆分成两个8-bit 的字符,读数据之后则需将两个字节合并起来,同时还要判别其中的SBCS 字符。没有充分利用数据库encoding 的作用,反而增加了编程的复杂度,ISO8859-1不是推荐的数据库encoding。JSP/Servlet编程时,可以先用数据库管理系统提供的管理功能检查其中的中文数据是否正确。

然后应当注意的是读出来的数据的encoding,JA VA 程序中一般得到的是Unicode。写数据时则相反。

4.5 定位问题时常用的技巧

定位中文encoding问题通常采用最笨的也是最有效的办法——在你认为有嫌疑的程序处理后打印字符串的内码。通过打印字符串的内码,你可以发现什么时候中文字符被转换成Unicode,什么时候Unicode被转回中文内码,什么时候一个中文字成了两个Unicode 字符,什么时候中文字符串被转成了一串问号,什么时候中文字符串的高位被截掉了……

取用合适的样本字符串也有助于区分问题的类型。如:”aa啊aa丂aa” 等中英相间、GB、GBK特征字符均有的字符串。一般来说,英文字符无论怎么转换或处理,都不会失真(如果遇到了,可以尝试着增加连续的英文字母长度)。

5. 结束语

其实JSP/Servlet 的中文encoding 并没有想像的那么复杂,虽然定位和解决问题没有定规,各种运行环境也各不尽然,但后面的原理是一样的。了解字符集的知识是解决字符问题的基础。不过,随着中文字符集的变化,不仅仅是java 编程,中文信息处理中的问题还是会存在一段时间的。

Java 编程技术中汉字问题的分析及解决

段明辉

自由撰稿人

2000 年11月8日

在基于 Java 语言的编程中,我们经常碰到汉字的处理及显示的问题。一大堆看不懂的乱码肯定不是我们愿意看到的显示效果,怎样才能够让那些汉字正确显示呢?Java 语言默认的编码方式是UNICODE ,而我们中国人通常使用的文件和数据库都是基于 GB2312 或者 BIG5 等方式编码的,怎样才能够恰当地选择汉字编码方式并正确地处理汉字的编码呢?本文将从汉字编码的常识入手,结合Java 编程实例,分析以上两个问题并提出解决它们的方案。

现在 Java 编程语言已经广泛应用于互联网世界,早在 Sun 公司开发Java 语言的时候,就已经考虑到对非英文字符的支持了。Sun 公司公布的 Java 运行环境(JRE)本身就分英文版和国际版,但只有国际版才支持非英文字符。不过在 Java 编程语言的应用中,对中文字符的支持并非如同 Java Soft 的标准规范中所宣称的那样完美,因为中文字符集不只一个,而且不同的操作系统对中文字符的支持也不尽相同,所以会有许多和汉字编码处理有关的问题在我们进行应用开发中困扰着我们。有很多关于这些问题的解答,但都比较琐碎,并不能够满足大家迫切解决问题的愿望,关于 Java 中文问题的系统研究并不多,本文从汉字编码常识出发,分析 Java 中文问题,希望对大家解决这个问题有所帮助。

汉字编码的常识

我们知道,英文字符一般是以一个字节来表示的,最常用的编码方法是ASCII 。但一个字节最多只能区分256个字符,而汉字成千上万,所以现在都以双字节来表示汉字,为了能够与英文字符分开,每个字节的最高位一定为1,这样双字节最多可以表示64K格字符。我们经常碰到的编码方式有 GB2312、BIG5、UNICODE 等。关于具体编码方式的详细资料,有兴趣的读者可以查阅相关资料。我肤浅谈一下和我们关系密切的 GB2312 和 UNICODE。GB2312 码,中华人民共和国国家标准汉字信息交换用编码,是一个由中华人民共和国国家标准总局发布的关于简化汉字的编码,通行于中国大陆地区及新加坡,简称国标码。两个字节中,第一个字节(高字节)的值为区号值加32(20H),第二个字节(低字节)

的值为位号值加32(20H),用这两个值来表示一个汉字的编码。UNICODE 码是微软提出的解决多国字符问题的多字节等长编码,它对英文字符采取前面加“0”字节的策略实现等长兼容。如“A”的 ASCII 码为0x41,UNICODE 就为0x00,0x41。利用特殊的工具各种编码之间可以互相转换。

Java 中文问题的初步认识

我们基于 Java 编程语言进行应用开发时,不可避免地要处理中文。Java 编程语言默认的编码方式是 UNICODE,而我们通常使用的数据库及文件都是基于GB2312 编码的,我们经常碰到这样的情况:浏览基于 JSP 技术的网站看到的是乱码,文件打开后看到的也是乱码,被 Java 修改过的数据库的内容在别的场合应用时无法继续正确地提供信息。

String sEnglish = “apple”;

String sChinese = “苹果”;

String s = “苹果 apple ”;

sEnglish 的长度是5,sChinese的长度是4,而 s 默认的长度是14。对于 sEnglish来说, Java 中的各个类都支持得非常好,肯定能够正确显示。但对于 sChinese 和 s 来说,虽然 Java Soft 声明 Java 的基本类已经考虑到对多国字符的支持(默认 UNICODE 编码),但是如果操作系统的默认编码不是UNICODE ,而是国标码等。从 Java 源代码到得到正确的结果,要经过“Java 源代码-> Java 字节码-> ;虚拟机->操作系统->显示设备”的过程。在上述过程中的每一步骤,我们都必须正确地处理汉字的编码,才能够使最终的显示结果正确。

“ Java 源代码-> Java 字节码”,标准的 Java 编译器 javac 使用的字符集是系统默认的字符集,比如在中文 Windows 操作系统上就是 GBK ,而在Linux 操作系统上就是ISO-8859-1,所以大家会发现在 Linux 操作系统上编译的类中源文件中的中文字符都出了问题,解决的办法就是在编译的时候添加encoding 参数,这样才能够与平台无关。用法是

javac –encoding GBK。

“ Java 字节码->虚拟机->操作系统”, Java 运行环境(JRE)分英文版和国际版,但只有国际版才支持非英文字符。 Java 开发工具包(JDK)肯定支持多国字符,但并非所有的计算机用户都安装了 JDK 。很多操作系统及应用软件为了能够更好的支持 Java ,都内嵌了 JRE 的国际版本,为自己支持多国字符提供了方便。

“操作系统->显示设备”,对于汉字来说,操作系统必须支持并能够显示它。英文操作系统如果不搭配特殊的应用软件的话,是肯定不能够显示中文的。

还有一个问题,就是在 Java 编程过程中,对中文字符进行正确的编码转换。例如,向网页输出中文字符串的时候,不论你是用

out.println(string); // string 是含中文的字符串

还是用

<%=string%>,都必须作 UNICODE 到 GBK 的转换,或者手动,或者自动。在 JSP 1.0中,可以定义输出字符集,从而实现内码的自动转换。用法是

<%@page ContentType=”text/html;charset=gb2312” %>

但是在一些 JSP 版本中并没有提供对输出字符集的支持,(例如 JSP 0.92),这就需要手动编码输出了,方法非常多。最常用的方法是

String s1 = request.getParameter(“keyword”);

String s2 = new String(s1.getBytes(“ISO-8859-1”),”GBK”);

getBytes 方法用于将中文字符以“ISO-8859-1”编码方式转化成字节数组,而“GBK”是目标编码方式。我们从以ISO-8859-1方式编码的数据库中读出中文字符串 s1 ,经过上述转换过程,在支持 GBK 字符集的操作系统和应用软件中就能够正确显示中文字符串 s2 。

Java 中文问题的表层分析及处理

.CLASS 文件存放在服务器端,由客户端的浏览器运行 APPLET , APPLET 只起调入 FRAME 类等主程序的作用。界面包括 Textfield ,TextArea,List,Choice 等。

I.取中文

用 JDBC 执行 SELECT 语句从服务器端读取数据(中文)后,将数据用 APPEND 方法加到 TextArea(TA),不能正确显示。但加到 List 中

时,大部分汉字却可正确显示。

将数据按“ISO-8859-1”编码方式转化为字节数组,再按系统缺省编码方式(Default Character Encoding)转化为 STRING ,即可在 TA 和 List 中正确显示。

程序段如下:

dbstr2 = results.getString(1);

//After reading the result from DB server,converting it to string.

dbbyte1 = dbstr2.getBytes(“iso-8859-1”);

dbstr1 = new String(dbbyte1);

在转换字符串时不采用系统默认编码方式,而直接采用“ GBK”或者“GB2312” ,在 A 和 B 两种情况下,从数据库取数据都没有问题。

II.写中文到数据库

处理方式与“取中文”相逆,先将 SQL 语句按系统缺省编码方式转化为字节数组,再按“ISO-8859-1”编码方式转化为 STRING ,最后送去

执行,则中文信息可正确写入数据库。

程序段如下:

sqlstmt = tf_input.getText();

//Before sending statement to DB server,converting it to sql statement.

dbbyte1 = sqlstmt.getBytes();

sqlstmt = newString(dbbyte1,”iso-8859-1”);

_stmt = _con.createStatement();

_stmt.executeUpdate(sqlstmt);

……

问题:如果客户机上存在 CLASSPATH 指向 JDK 的 CLASSES.ZIP 时(称为 A 情况),上述程序代码可正确执行。但是如果客户机只有浏览器,而没有 JDK 和 CLASSPATH 时(称为 B 情况),则汉字无法正确转换。

我们的分析:

1.经过测试,在 A 情况下,程序运行时系统的缺省编码方式为 GBK 或

者 GB2312 。在 B 情况下,程序启动时浏览器的 JAVA 控制台中出现如下错误信息:

Can't find resource for sun.awt.windows.awtLocalization_zh_CN

然后系统的缺省编码方式为“8859-1”。

2.如果在转换字符串时不采用系统缺省编码方式,而是直接采用

“GBK”或“GB2312”,则在 A 情况下程序仍然可正常运行,在 B 情况下,系统出现错误:

UnsupportedEncodingException。

3.在客户机上,把 JDK 的 CLASSES.ZIP 解压后,放在另一个目录中,

CLASSPATH 只包含该目录。然后一边逐步删除该目录中的 .CLASS 文

件,另一边运行测试程序,最后发现在一千多个 CLASS 文件中,只有

一个是必不可少的,该文件是:

sun.io.CharToByteDoubleByte.class。

将该文件拷到服务器端和其它的类放在一起,并在程序的开头 IMPORT

它,在 B 情况下程序仍然无法正常运行。

4.在 A 情况下,如果在 CLASSPTH 中去掉

sun.io.CharToByteDoubleByte.class ,则程序运行时测得默认编码

方式为“8859-1”,否则为“GBK”或“GB2312”。

如果 JDK 的版本为1.2以上的话,在 B 情况下遇到的问题得到了很好的解决,测试的步骤同上,有兴趣的读者可以尝试一下。

Java 中文问题的根源分析及解决

在简体中文 MS Windows 98 + JDK 1.3 下,可以用 System.getProperties() 得到 Java 运行环境的一些基本属性,类 PoorChinese 可以帮助我们得到这些属性。

类 PoorChinese 的源代码:

public class PoorChinese {

public static void main(String[] args) {

System.getProperties().list(System.out);

}

}

执行 java PoorChinese 后,我们会得到:

系统变量 file.encoding 的值为 GBK ,https://www.doczj.com/doc/273822466.html,nguage 的值为 zh ,user.region 的值为 CN ,这些系统变量的值决定了系统默认的编码方式是

GBK 。

在上述系统中,下面的代码将 GB2312 文件转换成 Big5 文件,它们能够帮助我们理解 Java 中汉字编码的转化:

import java.io.*;

import java.util.*;

public class gb2big5 {

static int iCharNum=0;

public static void main(String[] args) {

System.out.println("Input GB2312 file, output Big5 file.");

if (args.length!=2) {

System.err.println("Usage: jview gb2big5 gbfile big5file");

System.exit(1);

}

String inputString = readInput(args[0]);

writeOutput(inputString,args[1]);

System.out.println("Number of Characters in file:

"+iCharNum+".");

}

static void writeOutput(String str, String strOutFile) { try {

FileOutputStream fos = new FileOutputStream(strOutFile);

Writer out = new OutputStreamWriter(fos, "Big5");

out.write(str);

out.close();

}

catch (IOException e) {

e.printStackTrace();

e.printStackTrace();

}

}

static String readInput(String strInFile) {

StringBuffer buffer = new StringBuffer();

try {

FileInputStream fis = new FileInputStream(strInFile);

InputStreamReader isr = new InputStreamReader(fis, "GB2312");

Reader in = new BufferedReader(isr);

int ch;

while ((ch = in.read()) > -1) {

iCharNum += 1;

buffer.append((char)ch);

}

in.close();

return buffer.toString();

}

catch (IOException e) {

e.printStackTrace();

return null;

}

}

}

编码转化的过程如下:

ByteToCharGB2312 CharToByteBig5

GB2312------------------>Unicode------------->Big5

执行 java gb2big5 gb.txt big5.txt ,如果 gb.txt 的内容是“今天星期三”,则得到的文件 big5.txt 中的字符能够正确显示;而如果 gb.txt 的内容是“情人节快乐”,则得到的文件 big5.txt 中对应于“节”和“乐”的字符都是符号“?”(0x3F),可见 sun.io.ByteToCharGB2312 和

sun.io.CharToByteBig5 这两个基本类并没有编好。

正如上例一样, Java 的基本类也可能存在问题。由于国际化的工作并不是在国内完成的,所以在这些基本类发布之前,没有经过严格的测试,所以对中文字符的支持并不像 Java Soft 所声称的那样完美。前不久,我的一位技术上的朋友发信给我说,他终于找到了 Java Servlet 中文问题的根源。两周以来,他一直为 Java Servlet 的中文问题所困扰,因为每面对一个含有中文字符的字符串都必须进行强制转换才能够得到正确的结果(这好象是大家公认的唯一的解决办法)。后来,他确实不想如此继续安分下去了,因为这样的事情确实不应该是高级程序员所要做的工作,他就找出 Servlet 解码的源代码进行分析,因为他怀疑问题就出在解码这部分。经过四个小时的奋斗,他终于找到了问题的根源所在。原来他的怀疑是正确的, Servlet 的解码部分完全没有考虑双字节,直接把 %XX 当作一个字符。(原来 Java Soft 也会犯这幺低级的错误!)

如果你对这个问题有兴趣或者遇到了同样的烦恼的话,你可以按照他的步骤对 Servlet.jar 进行修改:

找到源代码 HttpUtils 中的 static private String parseName ,在返回前将 sb(StringBuffer)复制成 byte bs[] ,然后 return new

String(bs,”GB2312”)。作上述修改后就需要自己解码了:

HashTable

form=HttpUtils .parseQueryString(request.getQueryString())或者

form=HttpUtils.parsePostData(……)

千万别忘了编译后放到 Servlet.jar 里面。

五、关于 Java 中文问题的总结

Java 编程语言成长于网络世界,这就要求 Java 对多国字符有很好的支持。 Java 编程语言适应了计算的网络化的需求,为它能够在网络世界迅速成长奠定了坚实的基础。 Java 的缔造者(Java Soft)已经考虑到 Java 编程语言对多国字符的支持,只是现在的解决方案有很多缺陷在里面,需要我们付诸一些补偿性的措施。而世界标准化组织也在努力把人类所有的文字统一在一种编码之中,其中一种方案是 ISO10646 ,它用四个字节来表示一个字符。当然,在这种方案未被采用之前,还是希望 Java Soft 能够严格地测试它的产品,为用户带来更多的方便。

附一个用于从数据库和网络中取出中文乱码的处理函数,入参是有问题的字符串,出参是问题已经解决了的字符串。

String parseChinese(String in)

{

String s = null;

byte temp [];

if (in == null)

{

System.out.println("Warn:Chinese null founded!");

return new String("");

}

try

{

temp=in.getBytes("iso-8859-1");

temp=in.getBytes("iso-8859-1");

s = new String(temp);

}

{

System.out.println("Warn:Chinese null founded!");

return new String("");

}

try

{

temp=in.getBytes("iso-8859-1");

s = new String(temp);

}

catch(UnsupportedEncodingException e)

{

System.out.println (e.toString());

}

return s;

}

参考资料

?BBS 水木清华站的Java 讨论区

o中国最大的电子公告板的Java 讨论区,有众多高校的Java 爱好者在此进行关于Java 技术的讨论

作者简介

?段明辉,清华大学电子工程系学生

o现在正在清华大学微电子学研究所从事Java 智能卡微处理器的研究和开发

o领导BBS 水木清华站的Java 讨论组,为众多Java 技术应用者提供解决方案

宏 拼音转汉字

Option Explicit Option Compare Text Public Function HZQP(expression As String, Optional delimiter As String = " ", Optional limit As Integer = -1) As String 'expression ' 必需的?包含要转换的字符串? 'delimiter ' 可选的。用于标识分隔拼音的字符串字符。如果忽略,则使用空格字符(" ")作为分隔符。如果delimiter是一个长度为零的字符串,则返回仅包含一个元素,即完整的 expression字符串。 'limit ' 可选的。要返回拼音字符数,–1表示返回所有的拼音字符数,1表示返回拼音首字母。 Dim STR As String, arrWord(400) As String Dim i As Integer, j As Integer arrWord(1) = "吖a" arrWord(2) = "哎ai" arrWord(3) = "腤an" arrWord(4) = "肮ang" arrWord(5) = "凹ao" arrWord(6) = "八ba" arrWord(7) = "挀bai" arrWord(8) = "扳ban" arrWord(9) = "邦bang" arrWord(10) = "勹bao" arrWord(11) = "陂bei" arrWord(12) = "奔ben" arrWord(13) = "崩beng" arrWord(14) = "皀bi" arrWord(15) = "边bian" arrWord(16) = "杓biao" arrWord(17) = "憋bie" arrWord(18) = "邠bin" arrWord(19) = "仌bing" arrWord(20) = "拨bo" arrWord(21) = "峬bu" arrWord(22) = "嚓ca" arrWord(23) = "猜cai" arrWord(24) = "飡can" arrWord(25) = "仓cang" arrWord(26) = "撡cao" arrWord(27) = "冊ce" arrWord(28) = "嵾cen" arrWord(29) = "噌ceng" arrWord(30) = "*cha"

把汉字转换成拼音

把汉字转换成拼音 录入学生资料时需要输入姓名的汉字拼音,但怎样才能把姓名转换成拼音呢? 1、先把EXCEL中的学生姓名复制,再打开WORD,然后右键“选择性粘贴”,选择“无格式文 本”后确定。 2、再全选刚才学生的姓名,点击WORD中的“格式”菜单栏,找到“中文版式”里面的“拼音指 南”,(图1),可以把其中的“字号”由“5”设置大一些,如设置为“20”等后,然后“确定”,一次转换不成,可以再次转换,要注意一次可能转换不了,要多次才行。转换后效果,如(图2)。 3、全选所有的文字,右键选择“切换域代码”,出现如(图3)的文字,点击“编辑”菜单栏,找 到“查找(替换)”,切换到“替换”,在“查找内容”处输入:[)]*[)](注意是半角状态下的符号。),在“替换为”处输入:一个半角状态下的空格,然后点击下面的“高级”,在“使用通配符”打上“√”,最后点击“全部替换”。 4、接着用同样的方法,在“查找内容”处输入:EQ*[(]*[(](注意是半角状态下的符号。), 在“替换为”处输入:EQ ,(注意:EQ后还有一个半角状态下的空格)(图4),然后“全部替换”。效果如(图5),然后右键再选择“切换域代码”,剩下拼音。 5、全选所有拼音,复制后,新建一个EXCEL文档,按右键“选择性粘贴”,即可把汉字转换 成拼音。 图1 图2 图3

6、复制刚才的拼音到EXCEL 里,在EXCEL 中选择“编辑”,找到“定位”,点击“定位条件”,在里面选择“空值”后“确定”,对着其中已经选择的空格,右键“删除”,选择“下方单元格上移”后确定,即可把拼音复制到对应的姓名右边。 图4 图5 图6

如何在excel中把汉字转换成拼音

Excel自定义函数法: 1.启动Excel 2003(其它版本请仿照操作),打开相应的工作表; 2.执行“工具→宏→Visual Basic编辑器”命令(或者直接按“Alt+F11”组合键),进入Visual Basic编辑状态; 3.执行“插入→模块”命令,插入一个新模块。再双击插入的模块,进入模块代码编辑状态; 4.将代码输入其中; 5.代码输入完成后,关闭Visual Basic编辑窗口,返回Excel编辑状态; 6.自定义函数就可以用了,如:选中D2单元格,输入公式:=getpy(A2)。 有极个别的汉字不能转换,手动就可以了!很便了。 Function pinyin(p As String) As String i = Asc(p) Select Case i Case -20319 To -20318: pinyin = "a " Case -20317 To -20305: pinyin = "ai " Case -20304 To -20296: pinyin = "an " Case -20295 To -20293: pinyin = "ang " Case -20292 To -20284: pinyin = "ao " Case -20283 To -20266: pinyin = "ba " Case -20265 To -20258: pinyin = "bai " Case -20257 To -20243: pinyin = "ban " Case -20242 To -20231: pinyin = "bang " Case -20230 To -20052: pinyin = "bao " Case -20051 To -20037: pinyin = "bei " Case -20036 To -20033: pinyin = "ben " Case -20032 To -20027: pinyin = "beng " Case -20026 To -20003: pinyin = "bi " Case -20002 To -19991: pinyin = "bian " Case -19990 To -19987: pinyin = "biao " Case -19986 To -19983: pinyin = "bie " Case -19982 To -19977: pinyin = "bin " Case -19976 To -19806: pinyin = "bing " Case -19805 To -19785: pinyin = "bo " Case -19784 To -19776: pinyin = "bu " Case -19775 To -19775: pinyin = "ca " Case -19774 To -19764: pinyin = "cai " Case -19763 To -19757: pinyin = "can " Case -19756 To -19752: pinyin = "cang " Case -19751 To -19747: pinyin = "cao " Case -19746 To -19742: pinyin = "ce " Case -19741 To -19740: pinyin = "ceng " Case -19739 To -19729: pinyin = "cha " Case -19728 To -19726: pinyin = "chai "

汉字转拼音函数

--创建函数 IF OBJECT_ID('[fn_GetPinyin]')IS NOT NULL DROP FUNCTION [fn_GetPinyin] GO create function [dbo].[fn_GetPinyin](@words nvarchar(2000)) returns varchar(8000) as begin declare @word nchar(1) declare @pinyin varchar(8000) declare @i int declare @words_len int declare @unicode int set @i = 1 set @words =ltrim(rtrim(@words)) set @words_len =len(@words) while(@i <= @words_len)--循环取字符 begin set @word =substring(@words, @i, 1) set @unicode =unicode(@word) set @pinyin =ISNULL(@pinyin +SPACE(1),'')+ (case when unicode(@word)between 19968 and 19968+20901 then (select top 1 py from( select'a'as py,N'厑'as word union all select'ai',N'靉' union all select'an',N'黯' union all select'ang',N'醠' union all select'ao',N'驁' union all select'ba',N'欛' union all select'bai',N'瓸'--韛兡瓸 union all select'ban',N'瓣' union all select'bang',N'鎊' union all select'bao',N'鑤' union all select'bei',N'鐾' union all select'ben',N'輽' union all select'beng',N'鏰' union all select'bi',N'鼊' union all select'bian',N'變' union all select'biao',N'鰾' union all select'bie',N'彆' union all select'bin',N'鬢' union all select'bing',N'靐'

把汉字转换成拼音

把下面的所有容复制,粘贴到步骤4中的空白处Function pinyin(p As String) As String i = Asc(p) Select Case i Case -20319 To -20318: pinyin = "a " Case -20317 To -20305: pinyin = "ai " Case -20304 To -20296: pinyin = "an " Case -20295 To -20293: pinyin = "ang " Case -20292 To -20284: pinyin = "ao " Case -20283 To -20266: pinyin = "ba " Case -20265 To -20258: pinyin = "bai " Case -20257 To -20243: pinyin = "ban " Case -20242 To -20231: pinyin = "bang " Case -20230 To -20052: pinyin = "bao " Case -20051 To -20037: pinyin = "bei " Case -20036 To -20033: pinyin = "ben " Case -20032 To -20027: pinyin = "beng " Case -20026 To -20003: pinyin = "bi " Case -20002 To -19991: pinyin = "bian " Case -19990 To -19987: pinyin = "biao " Case -19986 To -19983: pinyin = "bie " Case -19982 To -19977: pinyin = "bin "

汉字转换拼音或拼音首字母(两个函数)

/* 根据汉字获取全拼 1.生成所有读音临时表 2.根据Chinese_PRC_CS_AS_KS_WS 排序获取读音 */ create function f_GetPy(@str varchar(100)) returns varchar(8000) as begin declare @re varchar(8000) –生成临时表 declare @t table(chr nchar(1) collate Chinese_PRC_CS_AS_KS_WS,py nvarchar(20)) insert into @t select’吖’,'a’ insert into @t select’厑’,'aes’ insert into @t select’哎’,'ai’ insert into @t select’安’,'an’ insert into @t select’肮’,'ang’ insert into @t select’凹’,'ao’ insert into @t select’八’,'ba’ insert into @t select’挀’,'bai’ insert into @t select’兡’,'baike’ insert into @t select’瓸’,'baiwa’ insert into @t select’扳’,'ban’ insert into @t select’邦’,'bang’ insert into @t select’勹’,'bao’ insert into @t select’萡’,'be’ insert into @t select’陂’,'bei’ insert into @t select’奔’,'ben’ insert into @t select’伻’,'beng’ insert into @t select’皀’,'bi’ insert into @t select’边’,'bian’ insert into @t select’辪’,'uu’ insert into @t select’灬’,'biao’ insert into @t select’憋’,'bie’ insert into @t select’汃’,'bin’ insert into @t select’冫’,'bing’ insert into @t select’癶’,'bo’ insert into @t select’峬’,'bu’ insert into @t select’嚓’,'ca’ insert into @t select’偲’,'cai’ insert into @t select’乲’,'cal’ insert into @t select’参’,'can’

excel-汉字转换成拼音简拼(只取首字母)

名字转换为首字母(VBA自定义函数) 1、打开EXCEL 2、按 ALT+F11 ,点击插入-插入模块,在右面窗口中粘贴下面代码,直接关闭窗口 3、输入公式=hztopy(A1),填充所有单元格 4、选中所有缩写,复制-选择性粘贴-数值(因为是自定义函数,只有在当前文件中可以显示结果,其他电脑因没有公式而显示错误) 5、使用条件格式,检索出含有汉字的单元格: 先点中一个单元格(设为D5),条件格式-新建格式规则-使用公式确定要设置格式的单元格:在下面对话框中输入公式 =LENB(D5)>LEN(D5),自己设置格式,确定后退出,再把该单元格的格式用格式刷刷所有单元格。有汉字的出现所设格式 6、选择自定义排序-排序依据“单元格颜色”-次序“无单元格颜色”“在底端”-确定。 7、将汉字手动改写为相应的字母。 8、核对多音字。 注:以上方法只可以在当前文件夹使用,如何将宏保存,使自定义函数可以在所有文件夹中使用 1、新建一个EXCEL 2、按 ALT+F11 ,点击插入-插入模块,在右面窗口中粘贴下面代码,直接关闭窗口 3、另存为-其他格式-文件名改为宏名称、保存类型选择“EXCEL加载宏(*,xlam)”,文件将自动保存在C:\Users\111\AppData\Roaming\Microsoft\AddIns文件夹。 4、打开需要工作的EXLEL,点击开始-EXCEL选项-加载项-转到(G)...-选中上面保存的宏名称-确定。 这样,在该电脑的所有EXCEL中,都可以直接使用自定义公式。

代码(只复制星号内的内容) ******************************************************************************* Function hztopy(hzpy As String) As String Dim hzstring As String, pystring As String Dim hzpysum As Integer, hzi As Integer, hzpyhex As Integer hzstring = Trim(hzpy) hzpysum = Len(Trim(hzstring)) pystring = "" For hzi = 1 To hzpysum hzpyhex = "&H" + Hex(Asc(Mid(hzstring, hzi, 1))) Select Case hzpyhex Case &HB0A1 To &HB0C4: pystring = pystring + "A" Case &HB0C5 To &HB2C0: pystring = pystring + "B" Case &HB2C1 To &HB4ED: pystring = pystring + "C" Case &HB4EE To &HB6E9: pystring = pystring + "D" Case &HB6EA To &HB7A1: pystring = pystring + "E" Case &HB7A2 To &HB8C0: pystring = pystring + "F" Case &HB8C1 To &HB9FD: pystring = pystring + "G" Case &HB9FE To &HBBF6: pystring = pystring + "H" Case &HBBF7 To &HBFA5: pystring = pystring + "J" Case &HBFA6 To &HC0AB: pystring = pystring + "K" Case &HC0AC To &HC2E7: pystring = pystring + "L" Case &HC2E8 To &HC4C2: pystring = pystring + "M" Case &HC4C3 To &HC5B5: pystring = pystring + "N" Case &HC5B6 To &HC5BD: pystring = pystring + "O" Case &HC5BE To &HC6D9: pystring = pystring + "P" Case &HC6DA To &HC8BA: pystring = pystring + "Q" Case &HC8BB To &HC8F5: pystring = pystring + "R" Case &HC8F6 To &HCBF9: pystring = pystring + "S" Case &HCBFA To &HCDD9: pystring = pystring + "T" Case &HEDC5: pystring = pystring + "T" Case &HCDDA To &HCEF3: pystring = pystring + "W" Case &HCEF4 To &HD1B8: pystring = pystring + "X" Case &HD1B9 To &HD4D0: pystring = pystring + "Y" Case &HD4D1 To &HD7F9: pystring = pystring + "Z" Case Else pystring = pystring + Mid(hzstring, hzi, 1) End Select Next hztopy = pystring End Function *******************************************************************************

汉字转换为拼音的代码

'*************************************************************************** '* MODULE NAME: HzToPy '* AUTHOR & DATE: tt.t '* 03 Apirl 2007 '* DESCRIPTION: 将中文字符串转换为拼音,就这些~ '* 有汉字得到拼音其实并不是我很关心的一个问题,只是发现已经公开'* 的方法有很大的缺陷,但WORD却做得很好,因此才尝试解决这个问题。 '* 过程比我预期的要曲折的多,主要是VBA实在是一种很受限制的语言。 '* 不过好在有Google和Olldbg,难题也仅仅是如何找到绕过限制的途径, '* 终于在5个小时内搞定了一切~ '* 时间比我预计的长了很多,因为我实在是不了解VBA,也不很熟悉OLE:"( '* 不过好在一切都解决了~~终于从VBA小白成长了一些。 '* 其实VBA也是很强大的~ '* '* Theory:废话了好多还是说说原理吧,虽然不是每个人都很关心~ '* WORD的拼音向导能够将汉字转成拼音全是倚仗微软拼音的帮助,'* 微软拼音2.0以上版本都提供了汉字到拼音的转换功能。 '* 微软拼音MSIME.China类中的IFELanguage接口具体实现了转换功能'* 不过MSIME.China中没有提供IDispatch接口,VBA的CreateObject 不支持 '* 调用这样的类,因此我们只好手工调用。CoCreateInstance可以创建类 '* 并获取IFELanguage接口,但我们无法直接调用,因为VBA不知道如何调用 '* IFELanguage接口的Method。这里困扰了我好久,原本希望能向其他语言那样 '* 声明接口结构,但VBA并不支持。万般无奈下只好在OLE相关DLL中寻找,期待能'* 找到代理函数简介调用接口的Method。呵呵~功夫不负苦心人终于在OLEAUT32中'* 找到了DispCallfunc。Google了一下,果然是我需要的。接口知道了,如何调用也 '* 清楚了,剩下的问题就是如何取得转换后的结果。IFELanguage.GetMorphResult会将 '* 转换的结果存在一个叫做tagMORRSLT的结构中,并返回指向tagMORRSLT 的指针。 '* 新问题又来了,VBA不支持指针...sigh,为什么其他语言很容易实现的功能VBA用起来 '* 就这么烦呢~幸好VBA读取内存的限制也好突破,只需调用ntdll的RtlMoveMemory。 '* 好了~一切限制都已解除,HzToPy终于正常工作了~~ '* 说起来一切顺理成章,可是寻找解决方法的过程真的很痛苦,不过VBA经验值大涨也算有所收获。 '* 下面就让代码来说话吧。 '* '* Memo: 改成类了,加入了拼音间加入分隔符和去掉注音的功能,请参照“模

excel 汉字转换成拼音简拼(只取首字母)

打开Excel->工具->宏->Viaual Basic编辑器 在弹出来的窗口中对着VBAproject点右键->插入->模块下面会出现一个名为"模块1",点击 在右边的空白栏中粘贴以下内容: Function pinyin(p As String) As String i = Asc(p) Select Case i Case -20319 To -20284: pinyin = "A" Case -20283 To -19776: pinyin = "B" Case -19775 To -19219: pinyin = "C" Case -19218 To -18711: pinyin = "D" Case -18710 To -18527: pinyin = "E" Case -18526 To -18240: pinyin = "F" Case -18239 To -17923: pinyin = "G" Case -17922 To -17418: pinyin = "H" Case -17417 To -16475: pinyin = "J" Case -16474 To -16213: pinyin = "K" Case -16212 To -15641: pinyin = "L" Case -15640 To -15166: pinyin = "M" Case -15165 To -14923: pinyin = "N" Case -14922 To -14915: pinyin = "O" Case -14914 To -14631: pinyin = "P"

如何在excel中把汉字转换成拼音

Excel自定义函数方法: 1.启动Excel 2003(其它版本请仿照操作),打开相应的工作表; 2.执行“工具→宏→Visual Basic编辑器”命令(或者直接按“Alt+F11”组合键),进入Visual Basic编辑状态; 3.执行“插入→模块”命令,插入一个新模块。再双击插入的模块,进入模块代码编辑状态; 4.将代码输入其中; 5.代码输入完成后,关闭Visual Basic编辑窗口,返回Excel编辑状态; 6.自定义函数就可以用了,如:选中D2单元格,输入公式:=getpy(A2)。 有极个别的汉字不能转换,手动就可以了!很方便了。 Function pinyin(p As String) As String i = Asc(p) Select Case i Case -20319 To -20318: pinyin = "a " Case -20317 To -20305: pinyin = "ai " Case -20304 To -20296: pinyin = "an " Case -20295 To -20293: pinyin = "ang " Case -20292 To -20284: pinyin = "ao " Case -20283 To -20266: pinyin = "ba " Case -20265 To -20258: pinyin = "bai " Case -20257 To -20243: pinyin = "ban " Case -20242 To -20231: pinyin = "bang " Case -20230 To -20052: pinyin = "bao " Case -20051 To -20037: pinyin = "bei " Case -20036 To -20033: pinyin = "ben " Case -20032 To -20027: pinyin = "beng " Case -20026 To -20003: pinyin = "bi " Case -20002 To -19991: pinyin = "bian " Case -19990 To -19987: pinyin = "biao " Case -19986 To -19983: pinyin = "bie " Case -19982 To -19977: pinyin = "bin " Case -19976 To -19806: pinyin = "bing " Case -19805 To -19785: pinyin = "bo " Case -19784 To -19776: pinyin = "bu " Case -19775 To -19775: pinyin = "ca " Case -19774 To -19764: pinyin = "cai " Case -19763 To -19757: pinyin = "can " Case -19756 To -19752: pinyin = "cang " Case -19751 To -19747: pinyin = "cao " Case -19746 To -19742: pinyin = "ce " Case -19741 To -19740: pinyin = "ceng " Case -19739 To -19729: pinyin = "cha " Case -19728 To -19726: pinyin = "chai "

相关主题
文本预览
相关文档 最新文档