UTF-16字符串:如何处理U + 10000?

时间:2014-02-13 08:37:38

标签: unicode utf-16

众所周知,当U + 10000上有一个字符时,UTF-16是可变长度的。

然而,.Net,Java和Windows WCHAR UTF-16字符串被视为固定长度...如果我使用超过U + 10000会怎样?

如果他们处理超过U + 10000,他们如何处理?例如,在.Net和Java char中是16位。所以一个char无法处理U + 10000 ..

(.net,java和windows只是示例..我正在谈论如何处理U + 10000.但我想我更愿意知道他们如何处理U + 10000,为了我的理解)


感谢@dystroy,我知道他们是如何处理的。但是有一个问题:如果字符串使用UTF-16代理,则随机访问操作(例如str[3])是O(N)算法,因为任何字符都可以是4字节或2字节!这个问题是如何处理的?

2 个答案:

答案 0 :(得分:3)

我在this QA回答了问题的第一部分:基本上,一些字符只是分布在多个Java char上。

要回答与随机访问unicode点str[3]相关的第二部分,有多种方法:

  • charAt是粗心的,只能快速而明显地处理字符
  • codePointAt返回32位int(但需要char索引)
  • codePointCount计算代码点数

是的,计算代码点 代价高昂且基本上O(N)。以下是它在Java中的用法:

2665    static int More ...codePointCountImpl(char[] a, int offset, int count) {
2666        int endIndex = offset + count;
2667        int n = 0;
2668        for (int i = offset; i < endIndex; ) {
2669            n++;
2670            if (isHighSurrogate(a[i++])) {
2671                if (i < endIndex && isLowSurrogate(a[i])) {
2672                    i++;
2673                }
2674            }
2675        }
2676        return n;
2677    }

UTF-16是一种处理代码点的错误格式,尤其是在您离开BMP时。大多数程序根本不处理代码点,这就是这种格式可用的原因。大多数String操作都很快,因为它们不与代码点交易:所有标准API都将char索引作为参数,而不用担心它们后面有什么样的符文点。

答案 1 :(得分:2)

通常这个问题根本没有得到解决。许多使用UTF-8或UTF-16的语言和库通过访问代码单元而不是代码点来进行子串或索引。那就是str[3]只会在这种情况下返回代理字符。当然,在这种情况下访问是恒定时间,但对于BMP(或ASCII)以外的任何内容,你必须小心你的工作。

如果你很幸运,有方法可以访问代码点,例如在Java String.codePointAt中。在这种情况下,您必须从头开始扫描字符串并确定代码点边界。

一般来说,即使访问代码点也不会让你受益匪浅,只是在图书馆一级。字符串通常最终用于与用户交互,在这种情况下,字形或视觉字符串长度变得比代码点更重要。在这种情况下,你还有更多的处理工作。