在Java中,如何处理Unicode字符和Java UTF-16代码点?

时间:2019-03-14 22:17:39

标签: java unicode codepoint

我在用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位,还是存在替代字符或组合字符?

2 个答案:

答案 0 :(得分:5)

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

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

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

  

字符边界分析使用户可以按照他们期望的方式与字符进行交互,例如,当光标在文本字符串中移动时。字符边界分析提供了正确的字符串浏览方式,而与字符的存储方式无关。

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

答案 1 :(得分:1)

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

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

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

通常,Unicode具有字符属性表(我不确定此处是否有正确的词),并且有可能发现您的代码点之一是组合字符。

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