网站公告列表

  没有公告

加入收藏
设为首页
联系站长
您现在的位置: 网络学院 >> 程序设计 >> Java编程 >> 文章正文
  JAVA中的字符与代码点            【字体:
JAVA中的字符与代码点
作者:佚名    文章来源:不详    点击数:    更新时间:2007-9-2    
摘要
本文介 Java 平台支持增字符的方式。
正在装载数据……
字符是 Unicode 准中代点超出 U+FFFF 的字符,因此它无法在 Java 言中描述为单个的 16 体(例如char数据型)。些字符一般极少用,但是,有些会在如中文或日文人名中用到,因此,在东亚国家,政府用程序通常会要求支持些字符。
Java 平台目前正在改,以便支持字符的理,这种进对现有的用程序影响微乎其微。新的低 API 在需要使用个的字符运行。不,大多数文本 API 均使用字符序列,例如String或字符数在,些均解释为 UTF-16 序列,而且, API 实现转变为正确地理增字符。些改已融入 Java 2 平台 5.0 版,准版 (J2SE)
详细释这些改之外,本文同时为应用程序开发确定和实现必要的更改提供指,以支持整个 Unicode 字符集的使用。
背景
Unicode 最初设计是作固定度的 16 位字符编码。在 Java 言中,基本数据char初衷是通提供一种简单的、能包含任何字符的数据型来充分利用这种设计点。不在看来,16 编码的所有 65,536 个字符并不能完全表示全世界所有正在使用或曾使用的字符。于是,Unicode 准已展到包含多达 1,112,064 个字符。那些超出原来的 16 位限制的字符被称作增字符。Unicode 2.0 版是第一个包含启用增字符设计的版本,但是,直到 3.1 版才收入第一批增字符集。由于 J2SE 5.0 版必支持 Unicode 4.0 版,因此它必支持增字符。
字符的支持也可能会成为东亚的一个普遍商要求。政府用程序会需要些增字符,以正确表示一些包含罕中文字符的姓名。出版用程序可能会需要些增字符,以表示所有的古代字符和体字符。中国政府要求支持 GB18030(一种对整个 Unicode 字符集编码的字符编码标准),因此,如果是 Unicode 3.1 版或更新版本,将包括增字符。台湾 CNS-11643 包含的多字符在 Unicode 3.1 中列字符。香港政府定了一种针对的字符集,其中的一些字符是 Unicode 中的增字符。最后,日本的一些供商正划利用增字符空中大量的用空收入 50,000 多个日文字字符体,以便从其有系迁移至基于 Java 平台的解决方案。
因此,Java 平台不需要支持增字符,而且必使用程序能方便地做到一点。由于增字符打破了 Java 言的基础设计构想,而且可能要求对编程模型行根本性的修改,因此,Java Community Process 召集了一个,以期找到一个适当的解决方案。被称 JSR-204 ,使用Unicode 增补字符支持的 Java 技术规范请求号。从技上来该专的决定适用于 J2SE 平台,但是由于 Java 2 平台企 (J2EE) J2SE 平台的最上,因此它可以直接受益,我期望 Java 2 平台袖珍版 (J2ME) 的配置也采用相同的设计方法。
,在了解 JSR-204 确定的解决方案之前,我需要先理解一些术语
点、字符编码方案、UTF-16些是指什
不幸的是,引入增字符使字符模型得更加复杂了。在去,我可以简单字符,在一个基于 Unicode 境(例如 Java 平台)中,假定字符有 16 位,而在我需要更多的术语。我会尽量介得相对简单一些如需了解所有详细讨论信息,您可以阅读Unicode 标准第 2 章 Unicode 术报 17“字符编码模型Unicode 专业人士可略所有介直接参本部分中的最后定
字符是抽象的最小文本位。它没有固定的形状(可能是一个字形),而且没有“A”是一个字符,“€”(德国、法国和多其他欧洲国家通用货币志)也是一个字符。
字符集是字符的集合。例如,字字符是中国人最先明的字符,在中文、日文文和越南文的写中使用。
编码字符集是一个字符集,它为每一个字符分配一个唯一数字。Unicode 准的核心是一个编码字符集,字母“A”编码为 004116 和字符“€”编码为20AC16Unicode 准始使用十六制数字,而且在在前面加上前“U+”,所以“A”编码书“U+0041”
点是指可用于编码字符集的数字。编码字符集定一个有效的代点范,但是并不一定将字符分配所有些代点。有效的 Unicode 点范 U+0000 U+10FFFFUnicode 4.0 将字符分配一百多万个代点中的 96,382 点。
字符是代点在 U+10000 U+10FFFF 的字符,也就是那些使用原始的 Unicode 16 设计无法表示的字符。从 U+0000 U+FFFF 的字符集有候被称基本多言面 (BMP)。因此,一个 Unicode 字符要属于 BMP,要属于增字符。
字符编码方案是从一个或多个编码字符集到一个或多个固定度代码单元序列的映射。最常用的代码单元是字,但是 16 位或 32 位整数也可用于内部理。UTF-32UTF-16 UTF-8 Unicode 准的编码字符集的字符编码方案。
UTF-32 即将一个 Unicode 点表示相同 32 位整数。很明,它是内部理最方便的表达方式,但是,如果作一般字符串表达方式,要消耗更多的内存。
UTF-16 使用一个或两个未分配的 16 位代码单元的序列 Unicode 编码 U+0000 U+FFFF 编码为一个相同 16 元。增字符编码为两个代码单元,第一个元来自于高代理U+D800 U+DBFF),第二个元来自于低代理范U+DC00 U+DFFF)。在概念上可能看起来似于多字节编码,但是其中有一个重要区 U+D800 U+DFFF 保留用于 UTF-16;没有分配字符作点。意味着,于一个字符串中的独的代码单元,件可以识别是否码单元表示某个单单元字符,或者是否码单元是某个双元字符的第一个或第二元。相当于某些传统的多字字符编码是一个著的改,在传统的多字字符编码中,字节值 0x41 既可能表示字母“A”,也可能是一个双字字符的第二个字
UTF-8 使用一至四个字的序列对编码 Unicode 编码U+0000 U+007F 使用一个字节编码U+0080 U+07FF 使用两个字U+0800 U+FFFF 使用三个字,而 U+10000 U+10FFFF 使用四个字UTF-8 设计原理:字节值 0x00 0x7F 表示代 U+0000 U+007FBasic Latin 字符子集,它对应 ASCII 字符集)。些字节值不会表示其他代点,一特性使 UTF-8 可以很方便地在件中将特殊的含义赋予某些 ASCII 字符。
下表所示几个字符不同表达方式的比
Unicode
U+0041
U+00DF
U+6771
U+10400
表示字形
UTF-32 码单
00000041
000000DF
00006771
00010400
UTF-16 码单
0041
00DF
6771
D801
DC00
UTF-8 码单
41
C3
9F
E6
9D
B1
F0
90
90
80

另外,本文在多地方使用术语字符序列或char序列概括 Java 2 平台识别的所有字符序列的容器:char[], java.lang.CharSequence实现(例如String),和java.text.CharacterIterator实现
这么术语。它与在 Java 平台中支持增字符有什么关系呢?
Java 平台中增字符的设计方法
JSR-204 作出的主要决定是如何在 Java API 中表示增字符,包括个字符和所有形式的字符序列。并排除了多方法:
*                   重新定基本char,使其具有 32 位,这样也会使所有形式的char序列成 UTF-32 序列。
*                   有的 16 char的基上,字符引入一新的 32 位基本型(例如,char32)。所有形式的 Char 序列均基于 UTF-16
*                   有的 16 char的基上,字符引入一新的 32 位基本型(例如,char32)。StringStringBuffer接受并行 API,并将它释为 UTF-16 序列或 UTF-32 序列;其他char序列继续基于 UTF-16
*                   使用int表示增的代点。StringStringBuffer接受并行 API,并将它释为 UTF-16 序列或 UTF-32 序列;其他char序列继续基于 UTF-16
*                   使用代理char,表示增点。所有形式的char序列基于 UTF-16
*                   引入一封装字符的StringStringBuffer接受新的 API,并将它释为字符的序列。
*                   使用一个CharSequence例和一个索引的合表示代点。
些方法中,一些在早期就被排除了。例如,重新定基本char,使其具有 32 位,这对于全新的平台可能会非常有吸引力,但是, J2SE ,它会与有的 Java 1、序列化和其他接口不兼容,更不用基于 UTF-32 的字符串要使用两倍于基于 UTF-16 的字符串的内存了。添加一型的char32可能会简单一些,但是仍然会出机和序列化方面的问题。而且,言更改通常需要比 API 更改有更的提前期,因此,前面两方法会字符支持来无法接受的延了在余下的方法中筛选出最方案,实现使用四不同的方法,在大量行低字符理的代java.util.regex包)中实现字符支持,并对这方法的易程度和运行表现进行了比
确定了一的方法:
*                   使用基本int在低 API 中表示代点,例如Character的静方法。
*                   将所有形式的char序列均解释为 UTF-16 序列,并促其在更高层级 API 中的使用。
*                   提供 API,以方便在各char和基于代点的表示法之转换
在需要,此方法既能提供一概念明且高效的个字符表示法,又能充分利用通可支持增字符的 API。同字符序列在个字符上的用,一点一般于国化的件很有好
这种方法中,一个char表示一个 UTF-16 码单元,这样对于表示代点有并不用。您会注意到,J2SE 术规在使用术语点和 UTF-16 码单元(表示法是相的)以及通用术语字符(表示法与该讨论没有系)。API 通常使用名称codePoint描述表示代点的int量,而 UTF-16 码单元的型当然char
将在下面两部分中了解到 J2SE 平台的实质变其中一部分介绍单个代点的低 API,另一部分介采用字符序列的高接口。
放的增字符:基于代点的 API
新增的低 API 两大:用于各char和基于代点的表示法之间转换的方法和用于分析和映射代点的方法。
最基本的转换方法是Character.toCodePoint(char high, char low)(用于将两个 UTF-16 码单转换为一个代点)和Character.toChars(int codePoint)(用于将指定的代转换为一个或两个 UTF-16 码单元,然后封装到一个char[]内。不,由于大多数情况下文本以字符序列的形式出,因此,另外提供codePointAtcodePointBefore方法,用于将代点从各字符序列表示法中提取出来:Character.codePointAt(char[] a, int index)String.codePointBefore(int index)是两典型的例子。在将代点插入字符序列,大多数情况下均有一些针对StringBufferStringBuilderappendCodePoint(int codePoint)方法,以及一个用于提取表示代点的int[]String构建器。
用于分析代码单元和代点的方法有助于转换过程:Character 中的isHighSurrogateisLowSurrogate方法可以识别用于表示增字符的charcharCount(int codePoint)方法可以确定是否需要将某个代转换为一个或两个char
但是,大多数基于代点的方法均能够对所有 Unicode 字符实现基于char的旧方法 BMP 字符所实现的功能。以下是一些典型例子:
*                   Character.isLetter(int codePoint)可根据 Unicode 识别字母。
*                   Character.isJavaIdentifierStart(int codePoint)可根据 Java 范确定代点是否可以启动标识
*                   Character.UnicodeBlock.of(int codePoint)可搜索代点所属的 Unicode 字符子集。
*                   Character.toUpperCase(int codePoint)可将定的代转换为其大写等字符。尽管此方法能支持增字符,但是它仍然不能解决根本的问题,即在某些情况下,逐个字符的转换无法正确完成。例如,德文字符“"ß"”应该转换为“SS”需要使用String.toUpperCase方法。
注意大多数接受代点的方法并不检查给定的int是否于有效的 Unicode 点范之内(如上所述,只有 0x0 0x10FFFF 的范是有效的)。在大多数情况下,该值是以确保其有效的方法生的,在些低 API 中反复检查其有效性可能会性能造成面的影响。在无法确保有效性的情况下,用程序必使用Character.isValidCodePoint方法确保代点有效。大多数方法于无效的代点采取的行没有特加以指定,不同的实现可能会有所不同。
API 包含便的方法,些方法可使用其他低 API 实现,但是组觉些方法很常用,将它添加到 J2SE 平台上很有意。不也排除了一些建便方法,这给提供了一次展示自己实现方法能力的机会。例如,组经过讨论,排除了一种针对String的新构建器(构建器可以建一个保持个代点的String)。以下是使用程序使用有的 API 提供功能的一种简便方法:
/**
 * 含有指定代点的新 String。
 */
String newString(int codePoint) {
    return new String(Character.toChars(codePoint));
}
您会注意到,在简单实现中,toChars方法始终创建一个中数列,数列使用一次即立即弃。如果方法在您的性能估中出,您可能会希望将其为针对普通的情况,即 BMP 字符:
/**
 * 含有指定代点的新 String
 * 针对 BMP 字符化的版本。
 */
String newString(int codePoint) {
    if (Character.charCount(codePoint) == 1) {