字和韩国的 Hangul 音节表。 目前已经定义了 40 000 多个不同的 Unicode 字符, 剩余 25 000 个空缺留给将来扩展使用。 其中大约 20
1
Unicode 协会是由 IBM、微软、Adobe、SUN、加州大学伯克利分校等公司和组织所组成的非营利性组织。
000 个字符用于汉字,另外 11 000 左右的字符用于韩语音节。Unicode 中 0~255 的字符与 ISO8859-1 中的 一致。 Unicode 编码对于英文字符采取前面加“0”字节的策略实现等长兼容。如“a”的 ASCII 码为 0x61, Unicode 码就为 0x00,0x61。 5.UTF-8 使用 Unicode 编码,一个英文字符要占用两个字节,在 Internet 上,大多数的信息都是用英文来表示 的,如果都采用 Unicode 编码,将会使数据量增加一倍。为了减少存储和传输英文字符数据的数据量,可 以使用 UTF-8 编码。 UTF-8 全称是 Eight-bit UCS Transformation Format(U
CS,Universal Character Set,通用字符集,UCS 是所有其他字符集标准的一个超集) 。对于常用的字符,即 0~127
的 ASCII 字符,UTF-8 用一个字节来表 示,这意味着只包含 7 位 ASCII 字符的字符数据在 ASCII 和 UTF-8 两种编码方式下是一样的。如果字符对 应的 Unicode 码是 0x0000,或在 0x0080 与 0x007f 之间,对应的 UTF-8 编码是两个字节,如果字符对应的 Unicode 码在 0x0800 与 0xffff 之间, 对应的 UTF-8 编码是三个字节。 因为中文字符的 Unicode 编码在 0x0800 与 0xffff 之间,所以数据如果是中文,采用 UTF-8 编码数据量会增加 50%。 Unicode 与 UTF-8 转换的规则简述如下: (1)如果 Unicode 编码的 16 位二进制数的前 9 位是 0,则 UTF-8 编码用 1 个字节来表示,这个字节的 首位是“0” ,剩下的 7 位与原二进制数据的后 7 位相同。例如: Unicode 编码:\u0061 = 00000000 01100001 UTF-8 编码:01100001 = 0x61 (2) 如果 Unicode 编码的 16 位二进制数的头 5 位是 0, UTF-8 编码用 2 个字节来表示, 则 首字节以 “110” 开头,后面的 5 位与原二进制数据除去前 5 个零后的最高 5 位相同;第二个字节以“10”开头,后面的 6 位与原二进制数据中的低 6 位相同。例如: Unicode 编码:\u00A9 = 00000000 10101001 UTF-8 编码:11000010 10101001 = 0xC2 0xA9 (3)如果不符合上述两个规则,则用三个字节表示。第一个字节以“1110”开头,后四位为原二进制 数据的高四位;第二个字节以“10”开头,后六位为原二进制数据中间的六位;第三个字节以“10”开头, 后六位为原二进制数据的低六位。例如: Unicode 编码:\u4E2D = 01001110 00101101 UTF-8 编码:11100100 10111000 10101101 = 0xE4 0xB8 0xAD 在 UTF-8 编码的多字节串中,第一个字节开头“1”的数目就是整个字符串中字节的数目。
17.1.2
对乱码产生过程的分析
为了让使用 Java 语言编写的程序能在各种语言的平台下运行, Java 在其内部使用 Unicode 字符集来表 示字符,这样就存在 Unicode 字符集和本地字符集进行转换的过程。当在 Java 中读取字符数据的时候,需 要将本地字符集编码的数据转换为 Unicode 编码,而在输出字符数据的时候,则需要将 Unicode 编码转换为 本地字符集编码。 例如,在中文系统下,从控制台读取一个字符“中” ,实际上读取的是“中”的 GBK 编码 0xD6D0, 在
Java 语言中要将 GBK 编码转换为 Unicode 编码 0x4E2D,此时,在内存中,字符“中”对应的数值就是 0x4E2D,当我们向控制台输出字符时,Java 语言将 Unicode 编码再转换为 GBK 编码,输出到控制台,中 文系统再根据 GBK 字符集画出相应的字符。 从上述过程来看,读取和写入的过程是可逆的,那么理应不会出现中文乱码
问题。然而,实际应用的 情形,比上述过程要复杂得多。在 Web 应用中,通常都包括了浏览器、Web 服务器、Web
应用程序和数
据库等部分,每一部分都有可能使用不同的字符集,从而导致字符数据在各种不同的字符集之间转换时, 出现乱码的问题。 在 Java 语言中,不同字符集编码的转换,都是通过 Unicode 编码作为中介来完成的。例如,GBK 编 码的字符“中”要转换为 ISO-8859-1(同 ISO8859-1)编码,其过程如下: 同 (1)因为在 Java 中的字符,都是用 Unicode 来表示的,所以 GBK 编码的字符“中”要转换为 Unicode 表示:0xD6D0->0x4E2D。 (2)将字符“中”的 Unicode 编码转换为 ISO-8859-1 编码,因为 Unicode 编码 0x4E2D 在 ISO-8859-1 中没有对应的编码,于是得到 0x3f,也