Java程序的中文与Unicode码相互转化解决
关键字:Java 中文 Unicode 编码转换
一、Appetite
在进行详细的编码转换原理阐述之前,我们要作两件事情:
1。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec首先检查操作系统用的语言。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec以Windows 2003 Server为例,可以在“控制面板”中的“区域和语言设置”中选择你的国家、语言,还有你的操作系统必须支持的语言。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec国籍&语言的设定会影响JRE的判 断情况。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec也许适当的设定能够帮你解决不少Java语言编码的问题。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec
2。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec更新新版本的JDK。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec因为新版本的JDK往往能够更好的支持新的特性,达到良好的语言迟迟效果。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec例如JDK5.0就已经更形了JDK1.2中的很多语言问题。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec
二、正餐
2.1 Unicode编码
2.1.1 Unicode——Java默认的编码
毫无疑问,Unicode作为容纳全球所有语言字符的超级字符集,是Java的首选字符集。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ecUnicode使用两个字节作为编码方式,总共容纳有6万多个 字符。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec因为使用16位进行字符编码,所以也称为UTF-16。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec然而即使这样,UTF-16也并不能充分囊括所有全世界正在使用或者曾经使用的字符,所以必 须对其进行扩充。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec于是后来的Unicode版本已经扩充到了1,112,064个字符,这种规模已经相当大了。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec但是这样仍然不能满足Unicode在世界 上的需求,所以必须进行必要的扩充。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec相比预Unicode1.0,后来的2.0版本已经支持扩展字符了,但是并没有真正的加入扩展字符集,这种状况一直持 续到了Unicode3.1版,才第一次在Unicode中引入了扩展字符集。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec但是Unicode的发展脚步并没有停滞,后来出现了Unicode4.0 标准,而这也正好是现在Java5.0版所必须而且已经提供支持的字符集。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec
显然“对增补字符的支持也可能会成为东亚市场的一个普遍商业要求。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec政府应用程序会需要这些增补字符,以正确表示一些包含罕见中文字符的姓名。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec出版应用程序 可能会需要这些增补字符,以表示所有的古代字符和变体字符。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec中国政府要求支持 GB18030(一种对整个 Unicode 字符集进行编码的字符编码标准),因此,如果是 Unicode 3.1 版或更新版本,则将包括增补字符。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec台湾标准 CNS-11643 包含的许多字符在 Unicode 3.1 中列为增补字符。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec香港政府定义了一种针对粤语的字符集,其中的一些字符是 Unicode 中的增补字符。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec最后,日本的一些供应商正计划利用增补字符空间中大量的专用空间收入 50,000 多个日文汉字字符变体,以便从其专有系统迁移至基于 Java 平台的解决方案。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec
因此,Java 平台不仅需要支持增补字符,而且必须使应用程序能够方便地做到这一点。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec由于增补字符打破了 Java 编程语言的基础设计构想,而且可能要求对编程模型进行根本性的修改,因此,Java Community Process 召集了一个专家组,以期找到一个适当的解决方案。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec该小组被称为 JSR-204 专家组,使用 Unicode 增补字符支持的 Java 技术规范请求的编号。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec从技术上来说,该专家组的决定仅适用于 J2SE 平台,但是由于 Java 2 平台企业版 (J2EE) 处于 J2SE 平台的最上层,因此它可以直接受益,我们期望 Java 2 平台袖珍版 (J2ME) 的配置也采用相同的设计方法。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec”
UTF-16的编码方式:
UTF-16 使用一个或两个未分配的 16 位代码单元的序列对 Unicode 代码点进行编码。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec值 0x0000 至 0xFFFF 编码为一个相同值的 16 位单元。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec增补字符编码为两个代码单元,第一个单元来自于高代理范围(0xD800 至 0xDBFF),第二个单元来自于低代理范围(U+DC00 至 U+DFFF)。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec这在概念上可能看起来类似于多字节编码,但是其中有一个重要区别:值 0xD800 至 0xDFFF 保留用于 UTF-16;没有这些值分配字符作为代码点。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec这意味着,对于一个字符串中的每个单独的代码单元,软件可以识别是否该代码单元表示某个单单元字符,或者是 否该代码单元是某个双单元字符的第一个或第二单元。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec这相当于某些传统的多字节字符编码来说是一个显著的改进,在传统的多字节字符编码中,字节值 0x41 既可能表示字母“A”,也可能是一个双字节字符的第二个字节。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec
2.1.2 节省空间的UTF-8
“如果我只能吃一块巧克力,我绝对不会买上一箱子的巧克力。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec”
是的,很多时候,特别是我们在处理程序的时候,所使用的并非是所有的Unicode字符,而仅仅是他们其中很小的一个部分,确切的说,这个部分不会比 ASCII多上多少。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec但是因为使用UTF-16,却不得不为此付出很多的存储空间来存储这些字符,这是一种可耻的浪费。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec因此,为了便于节省空间,无论是在 存储或者传输过程中,如果你只使用到了英文或者拉丁文,那么只需要8位来表示字符就足够了。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec这就是UTF-8的设计思想。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec但是,如果是在汉字或者亚洲语言 使用频率很高的地方,UTF-16依然将是首选。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec
但是值得注意的是,因为Unicode本身一直在进行版本更新,UTF-8当然也并非一成不变。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec对于经修改的过得UTF-8编码,在某些Java API的调用中会出现种种问题,特别是要注意在开发包含增补字符的文本与UTF-8进行转换的时候,可能会出现严重错误。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec
虽然Java本身对官方修订的UTF-8很熟悉,但是因为Java内部含有一套使用规范编码的机制,因此实际上,Java在使用UTF-8的时候,就并非 使用的是Unicode的UTF-8,而是一种叫做“Java modified UTF-8”(经 Java 修订的 UTF-8)或(错误地)直接称为“UTF-8”。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec而在J2SE5.0种,这种编码被统称为“modified UTF-8”(经修订的 UTF-8)。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec
“经修订的 UTF-8 和标准 UTF-8 之间之所以不兼容,其原因有两点。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec其一,经修订的 UTF-8 将字符 U+0000 表示为双字节序列 0xC0 0x80,而标准 UTF-8 使用单字节值 0x0。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec其二,经修订的 UTF-8 通过对其 UTF-16 表示法的两个代理代码单元单独进行编码表示增补字符 。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec每个代理代码单元由三个字节来表示,共有六个字节。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec而标准 UTF-8 使用单个四字节序列表示整个字符。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec
Java 虚拟机及其附带的接口(如 Java 本机接口、多种工具接口或 Java 类文件)在 java.io.DataInput 和 DataOutput 接口和类中使用经修订的 UTF-8 实现或使用这些接口和类 ,并进行序列化。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ecJava 本机接口提供与经修订的 UTF-8 之间进行转换的例程。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec而标准 UTF-8 由 String 类、java.io.InputStreamReader 和 OutputStreamWriter 类、java.nio.charset 设施 (facility) 以及许多其上层的 API 提供支持。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec
由于经修订的 UTF-8 与标准的 UTF-8 不兼容,因此切勿同时使用这两种版本的编码。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec经修订的 UTF-8 只能与上述的 Java 接口配合使用。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec在任何其他情况下,尤其对于可能来自非基于 Java 平台的软件的或可能通过其编译的数据流,必须使用标准的 UTF-8。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec需要使用标准的 UTF-8 时,则不能使用 Java 本机接口例程与经修订的 UTF-8 进行转换。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec”
UTF-8的编码方式:
UTF-8 使用一至四个字节的序列对编码 Unicode 代码点进行编码。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ecU+0000 至 U+007F 使用一个字节编码,U+0080 至 U+07FF 使用两个字节,U+0800 至 U+FFFF 使用三个字节,而 U+10000 至 U+10FFFF 使用四个字节。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ecUTF-8 设计原理为:字节值 0x00 至 0x7F 始终表示代码点 U+0000 至 U+007F(Basic Latin 字符子集,它对应 ASCII 字符集)。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec这些字节值永远不会表示其他代码点,这一特性使 UTF-8 可以很方便地在软件中将特殊的含义赋予某些 ASCII 字符。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec
2.1.3 同胞兄弟——UTF32
如果要问在Unicode家族谁的肚量最大,毫无疑问的是UTF-32。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec因为采用32位编码方式,所以会使得他的容量特别大!因为会有2的32次方个字符!同样的,会带来相应的问题,就是UTF-32的空间浪费的也比较严重。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec所以,比般情况下很少使用这种编码。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec
UTF-32的编码方式:
UTF-32 即将每一个 Unicode 代码点表示为相同值的 32 位整数。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec很明显,它是内部处理最方便的表达方式,但是,如果作为一般字符串表达方式,则要消耗更多的内存。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec
2.1.4 三种编码方式的比较
| Unicode 代码点 | ||||||||||||||
| 表示字形 | ||||||||||||||
| UTF-32 代码单元 |
|
|
|
|
||||||||||
| UTF-16 代码单元 |
|
|
|
|
||||||||||
| UTF-8 代码单元 |
|
|
|
|
更多的信息可以参见:
关于 Unicode 的编码,参见“The Unicode Standard, Version 3.0”一书(Addison-Wesley 出版)。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec
关于 UTF-8 编码,参见“Java I/O”一书的 399 页(O'Reilly 出版)。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec
关于 Java Class File 的格式与 Constant Pool,参见“Java Virtual Machine”一书(O'Reilly出版)。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec
如果想要知道你的系统到底使用什么样的字符集与字符打交道,可以使用如下代码片断得到字符集名称:
| String enc = System.getProperty"file.encoding"); System.out.println(enc); |
可能会得到下列字符集的名称:
GB2313:这是简体中文的标准。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec
GB18083:这是中文的扩展字符集。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec
HZ:同样是一种中文标准。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec
Big5:这是繁体中文标准。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec
CNS11643:台湾的官方标准繁体中文编码。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec
Cp937:繁体中文加上 6204 个使用者自定的字符
Cp948:繁体中文版 IBM OS/2 用的编码方式。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec
Cp964:繁体中文版 IBM AIX 用的编码方式。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec
EUC_TW:台湾的加强版 Unicode。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec
ISO2022CN:编码中文的一套标准。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec
ISO2022CN_CNS:编码中文的一套标准,繁体版,袭自 CNS11643。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec
MS950 或 Cp950:ASCII + Big5,用于台湾和香港的繁体中文 MS Windows操作系统。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec
2.2.2 问题来源
在Javac编译期间,也会先从OS中取得现在使用的字符集,此处设为A,之后把送入的字符串转化为Unicode编码,在编译之后再从Unicode转化为A型字符集。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec因此:
- 当你的操作系统国际设定错误,编译时就会产出错误的字符集编码。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec
- 一些比较lj的编译器会按照预先设定的字符集,而非OS所使用的字符集进行编码。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec
- 原是文件存盘时使用的字符集与编译器所使用的字符集无法匹配也会产生错误。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec
对于1和2,很好理解。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec对于3,例如我们使用的OS时GB2312,但是存盘时使用的编码字符集时UTF-8,这样java编译器编译文件的时候,就把UTF-8字符集当成GB2312字符集来处理,这样当然会出错。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec
可以使用一下代码片断来以制定的编码方式编译Java文件。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec
public OutputStreamWriter(OutputStream out, String encoding) throws UnsupportedEncodingException;
-
有时候,Reader和Writer之间进行通信的时候也可能出现编码错误,原因在于他们之间直接或者间接的使用到了I/O流,这样就可能导致编码转换时出现不统一的情况。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec
2.3.2 字符串与字节数组
Java的String类提供了非常丰富的功能借助与此,我们也能达到编码转换的功能。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec
常用的String构造函数如下:
String(byte[] bytes, int offset, int length, String charset);
String(byte[] bytes, String charset);
以上方法可以通过byte数组创建指定字符集的字符串,而下面的方法:
byte[] getBytes(String charset);
则可以将String转化为指定字符集的byte数组。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec
此外,还可以通过ByteArrayInputStream 或 ByteArrayOutputStream 串接到 InputStreamReader 或 OutputStreamWriter,来达到转码的目的。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec
2.4 其他问题和解决办法
然而Java本身涉及到编码的问题不止这些。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec曾经有位朋友编写一个可视花的zip应用程序。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec非常不幸的是,由于Java 本身的编码问题,使得他的程序在存储文件时,如果文件名是含有中文的,那么存储后的文件名不能够正确显示。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec这个问题困扰了他很久,虽然使用了本文中所提到 过的方法,但是依然不能够解决问题。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec无奈,在网络上查找了相关资料,发现如果不用java自己的zip包而改用Apache的zip包问题能够得到解决。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec
这就提示我们说,有的时候,当你面临Java的编码问题时,不妨利用第三方的工具包尝试解决往往能够收到不错的效果。:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec© 2004-2008 EDZH.COM.:N/ecYs^�S�vؚ�~z�^����� ��6q��/ec
三 总结
发表评论
| 标题: |
| 姓名: |
| 主页: |
|
验证码: |
| 内 容(1000个字符以内,不支持html) |
本站推荐
-
热点回顾
- 读Martin Fowler的Inversion of Control Containers and the Dependency Injection pattern
- java web ※#19977;※#23618;※#26550;※#26500;※#37197;※#32622;※#2
- java.applet.Applet※#30340;※#32593;※#32476;※#21151;※#33021;(※
- C#※#20351;※#29992;Hessian※#35843;※#29992;JAVA※#30340;※#20989
- ※quot;面向切面(AOP)※quot;与※quot;面向对象(OOP)※quot;(图)
- 专业图片网站轻松建—Arles Image Web Page Creator使用指南
- 用Solstice Enterprise Manager建立Java网络管理应用程序
- Java操作Word,Excel,Access,IE,OutLook, PDF 等
- Questions About The Telephone Interview
- JSTL 入门(2):探讨 core——使用定制标记进行流控制和 URL 管理
- IOPCBrowseServerAddressSpace 的使用(vc)
- 用.NET的System.Globalization来创建多语言应用程序
- Enterprise Library-Data Block oracle
- 配置Internet Information Service和RESIN
- 面向对象编程之:Java collection更有效管理elements
