非 BMP 字符判断及判断字符串中是否包含非 BMP 字符

判断一个字符是 BMP 字符还是非 BMP 字符(增补字符),以及判断字符串中是否包含非 BMP 字符。

在 Java 中,要判断一个字符是否为增补字符,也即所谓的非 BMP 字符,可以综合使用 String 类中的 codePointAt 和 Character 类中的 isSupplementaryCodePoint 方法,具体如下:

@Test
public void testSupplementaryCodePoint() throws Exception {
	// 一个非 BMP 字符
	String s = "𧿹";
	// 长度为 2
	assertThat(s.length()).isEqualTo(2);
	// 属于增补字符
	assertThat(Character.isSupplementaryCodePoint(s.codePointAt(0))).isTrue();
}

当然也可以简单地尝试将这个字符赋值给一个 char 变量,char 变量只能接受一个 BMP 字符,如果是非 BMP 字符,则编译不通过。

如果是一串的字符,想知道其中是否存在非 BMP 字符,则可以使用 codePointCount 方法:

@Test
public void testCodePointCount() throws Exception {
	String normalStr = "hi你";
	String strContainNoneBMP = "h𧿹你";
	
	// 两者的 length 不同
	assertThat(normalStr.length()).isEqualTo(3);
	assertThat(strContainNoneBMP.length()).isEqualTo(4);
	
	// 两者的码点数( code point count)却是相同的
	assertThat(normalStr.codePointCount(0, normalStr.length())).isEqualTo(3);
	assertThat(strContainNoneBMP.codePointCount(0, strContainNoneBMP.length())).isEqualTo(3);
}

这点其实在之前的字符集与编码(五)——代码单元及 length 方法其实也提到过。

如果含有非 BMP 字符,则 string 的 length 和 codePointCount 的值是不等的,更具体地讲,length 的值要大于 codePointCount 的值。