C#的StringInfo和TextElementEnumerator无法正确识别字素

时间:2018-09-20 11:00:22

标签: c# string unicode icu grapheme

在C#中,StringInfoTextElementEnumerator类提供文本元素的方法和属性。 然后here,我们可以找到文本元素的定义。

  

.NET Framework将text元素定义为以下文本单位:   显示为单个字符,即字素。文字元素   可以是以下任意一种:

是的,它表示文本元素是.NET中的字素。我还亲自测试了一些unicode字符,直到我测试了一个韩文字母“ ”之前,这确实是真的。

众所周知,某些Unicode字符由多个代码点组成。同样,我们可能会遇到代码点序列,这就是我使用StringInfoTextElementEnumerator而不是简单的String的原因。

StringInfoTextElementEnumerator可以判断Char是否是正确的代理对。正如预期的那样,由多个代码点组成的Unicode字符“ \ u0061 \ u0308”被识别为一个文本元素。但是对于“ \ u1100 \ u1161”,它并不能说它也是一个文本元素。

“ \ u1100”是前导字母“ㄱ”,而“ \ u1161”是元音字母“ㅏ”。它们可以是单独的字符,并可以像我在此处编写的那样显示给用户,您现在可以看到它们。但是,如果将它们一起使用,它们将被呈现为一个字符“가”而不是“ㄱㅏ”。

有两种方式来表示朝鲜语字符“가”:

  1. 使用 Hangul音节中的单个代码点 U + AC00
  2. 使用来自 Jamo 的两个代码点 U + 1100 U + 1161

大多数情况下使用前者。坦白说,后者很少使用。我完全无法想象何时使用它。 无论如何,第一个字母只是一个预组合字母,第二个字母是 Lead Vowel 的序列,被视为一个字符。渲染时,它们看起来完全一样,并且两者实际上在规范上是等效的。 同样,以下行在C#中返回true:

"\u1100\u1161".Normalize() == "\uAC00"

我想知道为什么当C#认为Normalize()并不是一个完整的文本元素时,这里的效果很好。 我以为它与.NET的版本有关,但事实并非如此。甚至在Mono中也会发生这种事情。

我也用ICU对此进行了测试,它可以正确将“ \ u1100 \ u1161”视为一个字素! 我最初以为StringInfoTextElementEnumerator可以在某些简单情况下消除对 ICU4C 的需求,所以现在我很失望。.

这是我的问题:

我在这里做错什么了吗?

.NET中的文本元素不是用户在ICU中所感知的字符吗?

1 个答案:

答案 0 :(得分:2)

这里的基本问题是,根据韩国标准KS X 1026,两个jams 与它们的组合形式不同。实际上,此确切示例已在官方标准中使用(请参见6.2节)。

长话短说,Microsoft尝试遵循该标准,但其他操作系统和应用程序不一定要遵循该标准。因此,您可以从其他软件/平台上获得“格式错误”的内容,这些内容在Windows / .NET中似乎被错误地解析,即使在这些平台上被“正确”地解析也是如此。

您要么需要首先确保您的数据正确形成(鉴于 de-facto 标准完全忽略了 official 标准,但不太可能)否则您将需要使用ICU(或类似的库)来处理这些情况。