众所周知,当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字节!这个问题是如何处理的?
答案 0 :(得分:3)
我在this QA回答了问题的第一部分:基本上,一些字符只是分布在多个Java char
上。
要回答与随机访问unicode点str[3]
相关的第二部分,有多种方法:
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
中。在这种情况下,您必须从头开始扫描字符串并确定代码点边界。
一般来说,即使访问代码点也不会让你受益匪浅,只是在图书馆一级。字符串通常最终用于与用户交互,在这种情况下,字形或视觉字符串长度变得比代码点更重要。在这种情况下,你还有更多的处理工作。