标签:
Java从1.5版本开始,加入了unicode辅助平面的支持。本文在JDK1.6上测试。
相关的API主要在Character和String类里。以下这段话是Character的文档说明摘抄。
==================================================================================================
Character 类在对象中包装一个基本类型 char 的值。Character 类型的对象包含类型为 char 的单个字段。 此外,该类提供了几种方法,以确定字符的类别(小写字母,数字,等等),并将字符从大写转换成小写,反之亦然。 字符信息基于 Unicode 标准,版本 4.0。 Character 类的方法和数据是通过 UnicodeData 文件中的信息定义的,该文件是 Unicode Consortium
维护的 Unicode Character Database 的一部分。此文件指定了各种属性,其中包括每个已定义 Unicode 代码点或字符范围的名称和常规类别。 此文件及其描述可从 Unicode Consortium 获得,网址如下: http://www.unicode.org 。char 数据类型(和 Character 对象封装的值)基于原始的 Unicode 规范,将字符定义为固定宽度的 16 位实体。Unicode 标准曾做过修改,以允许那些其表示形式需要超过 16 位的字符。合法代码点 的范围现在是从
U+0000 到 U+10FFFF,即通常所说的 Unicode 标量值。(请参阅 Unicode 标准中 U+n 表示法的定义。) 从 U+0000 到 U+FFFF 的字符集有时也称为 Basic Multilingual Plane (BMP)。代码点大于 U+FFFF 的字符称为增补字符。Java 2 平台在 char 数组以及 String 和 StringBuffer 类中使用 UTF-16 表示形式。在这种表现形式中,增补字符表示为一对 char 值,第一个值取自高代理项 范围,即 (\uD800-\uDBFF),第二个值取自低代理项
范围,即 (\uDC00-\uDFFF)。 所以,char 值表示 Basic Multilingual Plane (BMP) 代码点,其中包括代理项代码点,或 UTF-16 编码的代码单元。int 值表示所有 Unicode 代码点,包括增补代码点。int 的 21 个低位(最低有效位)用于表示 Unicode 代码点,并且 11 个高位(最高有效位)必须为零。除非另有指定,否则与增补字符和代理项 char 值有关的行为如下: 只接受一个 char 值的方法无法支持增补字符。它们将代理项字符范围内的 char
值视为未定义字符。例如,Character.isLetter(‘\uD840‘) 返回false,即使是特定值,如果在字符串的后面跟着任何低代理项值,那么它将表示一个字母。 接受一个 int 值的方法支持所有 Unicode 字符,其中包括增补字符。例如,Character.isLetter(0x2F81A) 返回 true,因为代码点值表示一个字母(一个 CJK 象形文字)。 在 Java SE API 文档中,Unicode 代码点 用于范围在 U+0000 与 U+10FFFF 之间的字符值,而 Unicode
代码点 用于作为 UTF-16 编码的代码单元的 16 位 char 值。有关 Unicode 技术的详细信息,请参阅 Unicode Glossary。
====================================================================================================
可以看出,增补字符是用一个长度为2的char数组表示的,分别表示高代理项和低代理项。用法可以参考如下的例子
<span style="font-family:SimSun;font-size:14px;"> public static int codePointAt(char[] a, int index) { return codePointAtImpl(a, index, a.length); }</span>
<span style="font-family:SimSun;font-size:14px;"> static int codePointAtImpl(char[] a, int index, int limit) { char c1 = a[index++]; if (isHighSurrogate(c1)) { if (index < limit) { char c2 = a[index]; if (isLowSurrogate(c2)) { return toCodePoint(c1, c2); } } } return c1; }</span>
<span style="font-family:SimSun;font-size:14px;"> public static int toCodePoint(char high, char low) { return ((high - '\uD800') << 10) + (low - '\uDC00') + 65536; }</span>
可以看出,如果是输入增补字符数组,那么,当传入索引是0的时候,就会返回整个增补字符的码点,当传入索引是1的时候,就会返回增补字符数组中第二个字符的码点。
<span style="font-family:SimSun;font-size:14px;">public static void main(String[] args) { char[] c = Character.toChars(Integer.parseInt("1D306", 16));//1D306是一个辅助平面字符 System.out.println(Character.codePointAt(c, 0));//输出119558,这个是1D306对应的10进制值 System.out.println(Character.codePointAt(c, 1));//输出57094,这个是c[1]对应字符的10进制值 }</span>
当传入的字符数组是都是基本平面的字符时,直接返回传入的索引对应的基本平面字符的码点。
<span style="font-family:SimSun;font-size:14px;"> public static void main(String[] args) { char[] c = {'a', 'b', '测', '试'}; System.out.println(Character.codePointAt(c, 0));//97 System.out.println(Character.codePointAt(c, 1));//98 System.out.println(Character.codePointAt(c, 2));//27979 System.out.println(Character.codePointAt(c, 3));//35797 System.out.println((char) 97);//a System.out.println((char) 98);//b System.out.println((char) 27979);//测 System.out.println((char) 35797);//试 }</span>
<span style="font-family:SimSun;font-size:14px;"> public static void main(String[] args) { char[] c = Character.toChars(Integer.parseInt("1D306", 16));//1D306是一个辅助平面字符 System.out.println(Character.codePointAt(c, 0));//输出119558,这个是1D306对应的10进制值 System.out.println(Character.codePointAt(c, 1));//输出57094,这个是c[1]对应字符的10进制值 System.out.println(new String(c).codePointAt(0));//输出119558,这个是1D306对应的10进制值 System.out.println(new String(c).codePointAt(1));//输出57094,这个是c[1]对应字符的10进制值 String str = "abcdefg" + new String(c); System.out.println(str.length());//9 System.out.println(str.codePointCount(0, str.length()));//8 }</span>上面的例子,字符串长度是9,因为字符U+1D306需要一个长度为2的字符数组来表示,而实际上代码点只有1个,所以会分别返回9和8。
标签:
原文地址:http://blog.csdn.net/gjb724332682/article/details/51324036