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

Unicode UTF-16字符串:如何处理U+;10000?,unicode,utf-16,Unicode,Utf 16,正如我们所知,当有一个字符超过U+10000时,UTF-16是可变长度的 但是,.Net、Java和WindowsWCHARUTF-16字符串被视为固定长度。。。如果我使用超过U+10000会发生什么 如果他们处理超过U+10000,他们如何处理?例如,在.Net和Java中,char是16位。因此,一个char无法处理超过U+10000的数据 (.net、java和windows只是一个例子..我说的是如何处理U+10000。但我想我更想知道他们如何处理U+10000,以便于我理解) 多亏了

正如我们所知,当有一个字符超过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字节!如何处理这个问题?

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

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

  • 粗心大意,只以快速和明显的方式处理字符
  • 返回32位整数(但需要字符索引)
  • 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    }
2665静态整数更多…codePointCountImpl(字符[]a,整数偏移量,整数计数){
2666 int ENDIX=偏移量+计数;
2667 int n=0;
2668(int i=偏移量;i

UTF-16对于处理代码点来说是一种糟糕的格式,尤其是当您离开BMP时。大多数程序根本不处理代码点,这就是这种格式可用的原因。大多数字符串操作都很快,因为它们不处理代码点:所有标准API都将
char
索引作为参数,不必担心它们背后有什么样的符文点。

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

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


一般来说,即使访问代码点也不会给您带来太多好处,不过,这只是在库级别。字符串通常最终用于与用户交互,在这种情况下,字形或可视字符串长度变得比代码点更重要。在这种情况下,您需要做更多的处理。

TLDR:一些字符只是分布在多个Java字符上…@dystroy请参见edit@dystroy嗯。。我们没有随机存取的机会是O(N)吗?听起来很糟糕。你到底想要什么样的答案?是的,访问字符串中的随机代码点是昂贵的。这是我想要的答案,即使我似乎不满意。。。无论如何,如果是这样,在每个字符串相关的操作中都需要O(N)来支持U+10000以上?哦哦,在我的问题中,
str[3]
表示第三个字符。。java就是一个例子。我说的是如何处理,而不是java方法处理什么。ASCII?希望32位中的ASCII码不止一个。也许这部分答案不清楚。@dystroy:UTF-8和UTF-16是可变长度的。一个使ASCII字符的访问变得简单,另一个使BMP字符的访问变得简单。对于所有其他问题,您必须处理可变长度问题。这就是这里的意思。这就是说,除非你按几十或几百吉比特处理字符串,否则你不可能真正注意到原始索引或实际查找代码点的区别。哦,你说的是UTF-8。好啊我认为这会使答案变得更复杂。@ikh:没什么区别。Java也是我回答中的一个例子。如果你想,我也可以加上C#或Qt,但这没关系。早期获得unicode支持并因此被UTF-16卡住的大多数东西走简单的路线,忽略代码点路线(除非它们是专门为文本处理而构建的,但是它们可能在内部使用UTF-32),只给您代码点。Python是一个很好的例外,它甚至完全隐藏了Unicode字符串的底层字节表示形式。谢谢!那么,忽略U+10000不是一个坏选择吗?我想我应该考虑UTF 32如果我工作超过U + 10000…我不明白你的需要。你怎么处理你的代码点呢?嗯,我正在写一个字符串库,我想我应该完全了解这个问题。不知道你的问题,你可能不应该使用UTF-32。UTF-8是最常用的方法。。好啊谢谢你的帮助!