相关的“编码” 全面分析 Java 相关的“编码”问题
本文说明
Java 程序员遇到的一个很头痛的问题就是编码问题。 一旦开发与系统平台及网络相关的 程序而需要传输中文字符时, 若不能正确掌握编码的知识, 将频频出现乱码问题而扰乱开发 计划。目前已经存在大量的关于编码问题的讲解。个人觉得这些
文档主要是教“怎样解决目 前问题”而非“为什么有这个问题” 。希望本文能够帮助读者从根本上了解编码原理,以及
软件开发过程中出现乱码的原因,而非仅仅是解决某个具体问题。
字符集与编码标准
字符集 UNICODE 从概念上讲,字符集并不完全等同与编码标准,这两个概念的区别很模糊。 (未经过文 献证实,只是以掌握的知识这么认为) 。大家都清楚 Java 使用的是 UNICODE 字符集。请注意 这里使用的是“字符集”关键字。下面以 UNICODE 为例字符集与编码标准。 UNICODE 是一套字符集而非编码标准。UNICODE 字符集并非一直不变,目前流行使用 的版本是使用 2 个字节来存储理论数量为 256x256=65535(个)的字符集。两个字节能表示的 范围也就是这个数字,以 16 进制表示就是 0x0000-0xFFFF。这 65535(个)已经足够收录目前 世界上主要语言的大多数字符了,保证日常通信是没问题的。最新的 UNICODE 标准已经可 以支持几百万个字符了,当然随之而来的则是一个字符占用的字节数将更大。 在目前使用的 JRE 版本中,一个中文字符是使用两个字节的内存空间来存储的。在 Java 中测试 UNICODE 的相关功能是非常容易的: 首先是查看一个中文字符的 UNICODE 编码值(特别注意,这里指的是字符集中一个字 符所代表的数字,它是存放在内存中的) 。运行如下代码将可以得到: char ch1 = '汉' ; int nch1 = (int)ch1 ; System.out.println("汉:" + Integer.toHexString(nch1)); 运行结果为:汉:6c49。 也就是说“汉”这个字符在内存中实际上是占用了两个字节的空间,一个字节存放的是 “6C” 而另一个字节存放的是 “49” 这个十六进制数 。 “0x6c49” 所代表的数字则是在 UNICODE 字符集标准中“汉”这个字对应的数字值。
Java 中提供了对“转码”相当好的支持,使用的时候也非常方便。请运行下面的代码: String str = “\u6c49” ; System.out.println("6C49 --> " + str); 运行结果:6C49 --> 汉。 “\U” 是将十六进制数转化成字符的转义字符。 它只对它后面紧跟上的四个字符起作用。 比如说:‘a’的 UNICODE 数字编码是 61) ( String str = “\u61” ; 字字符” String str = “\ugf61” ; String str = “\u0061”; //代码无法通过编译,提示不正确的 UNICODE 编码。 //代码能够运行,打印 str 的结果为”a” 。 //这句代码是
通不过编译的,”\u 后面至少要 4 位十六进制的数
在 JRE 的 bin 目录下有一个 native2ascii.exe 程序,它可以提供对中文字符的转码,转化 成上述的\uXXXX 的格式。因为这种格式的字符串可以在完全不支持中文的环境中存储和传 输,并且也可以被 Java
程序轻松的还原(String str = “\u6c49” ;这样就还原了,够简单了) 。 实际上手工编写一个 native2ascii.exe 的功能也是很简单的,前面已经介绍了其中的原理了。
Java 中 UNICODE 字符集是表示在内存中的字符的编码,是和 String 类紧密相关的。一 旦一个字符串建立,这些字符在内存中所存放的十六进制数就是根据 UNICODE 而来。在不 需要写入文件和网络传输的情况下它的编码都是统一的。 换句话说 String 类在处理字符的时 候会将对象自身存储的“字节数组”以 UNICODE 来分析,两两字节来读取,将两个字节作 为一组当成一个字符来处理。 (注意这里) 这种不需要转换编码的字符串处理过程是程序员非常希望见到的。但实际上 Java 系统 的运行其实到处都存在转码的处理。 因为不可能数据只存在于内存中吧, 只在内存中处理