Java中unicode增补字符(辅助平面)相关用法简介

前言

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数组表示的,分别表示高代理项和低代理项。用法可以参考如下的例子

例一

codePointAt方法的源码如下:

public static int codePointAt(char[] a, int index) {
	return codePointAtImpl(a, index, a.length);
    }
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;
    }
public static int toCodePoint(char high, char low) {
        return ((high - '\uD800') << 10)
            + (low - '\uDC00') + 65536;
    }

可以看出,如果是输入增补字符数组,那么,当传入索引是0的时候,就会返回整个增补字符的码点,当传入索引是1的时候,就会返回增补字符数组中第二个字符的码点。

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进制值
    }

当传入的字符数组是都是基本平面的字符时,直接返回传入的索引对应的基本平面字符的码点。

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);//试
    }

例二

String类的length和codePointCount方法,在处理增补字符时,返回的数据是不一样的,而对于基本平面来说,返回值都是一样的。
length返回字符串长度,codePointCount放回代码点数量。
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
    }
上面的例子,字符串长度是9,因为字符U+1D306需要一个长度为2的字符数组来表示,而实际上代码点只有1个,所以会分别返回9和8。



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值