2

我正在为 Java 10 中的 Unicode 字符而苦苦挣扎。
我正在使用 java.text.BreakIterator 包。对于这个输出

myString="ab"  hex=0061d835dcde0062
myString.length()=4 
myString.codePointCount(0,s.length())=3
BreakIterator output:
    a    hex=0061           
        hex=d835dcde          
    b    hex=0062

似乎是正确的。

使用相同的 Java 代码,然后使用此输出

myString="G̲íl"  hex=0047033200ed006c  
myString.length()=4 
myString.codePointCount(0,s.length())=4
BreakIterator output:   
    G̲    hex=00470332  
    í    hex=00ed  
    l    hex=006c  

似乎也正确,除了 codePointCount=4。
为什么不是 3,有没有办法在不使用 BreakIterator 的情况下获得 3 值?

我的目标是确定字符串的所有(输出)字符是否都是 16 位的,或者是否存在代理或组合字符?

4

2 回答 2

5

“G̲íl”四个代码点:U+0047、U+0332、U+00ED、U+006C。

U+0332 是一个组合字符,但它一个单独的代码点。这与您的第一个示例不同,后者需要使用代理对(2 个 UTF-16 代码单元)来表示 U+1D4DE - 但后者仍然是单个代码

BreakIterator在文本中找到边界 - 从这个意义上说,此处组合的两个代码点之间没有边界。从文档中:

字符边界分析允许用户按他们期望的方式与字符进行交互,例如,在文本字符串中移动光标时。字符边界分析提供通过字符串的正确导航,而不管字符是如何存储的。

所以我认为这里一切正常。

于 2019-03-14T22:23:16.443 回答
1

一个代码点对应一个 Unicode 字符。

Java 以 UTF-16 表示 Unicode,即以 16 位为单位。代码点值大于 U+FFFF 的字符由一对“代理字符”表示,如您的第一个示例所示。因此 3 的第一个结果。

在第二种情况下,您有一个不是单个 Unicode 字符的示例。它是一个字符 LETTER G,后跟另一个字符 COMBINING CHARACTER LOW LINE。这是每个定义的两个代码点。因此 4 的第二个结果。

一般来说,Unicode 有字符属性表(我不确定我在这里是否有正确的词),并且可以发现您的代码点之一是组合字符。

看一下 Character 类。getType(character) 将告诉您代码点是组合字符还是代理项。

于 2019-03-14T22:33:28.217 回答