c# - C#'s StringInfo and TextElementEnumerator can' t 正确识别字素

标签 c# string unicode icu grapheme

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

The .NET Framework defines a text element as a unit of text that is displayed as a single character, that is, a grapheme. A text element can be any of the following:

是的,它说文本元素是 .NET 中的字素。我自己也用一些 unicode 字符进行了测试,直到我测试了一个韩文字母“і”,这看起来确实是真的。

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

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

“\u1100”是前导字母“ㄱ”,“\u1161”是元音字母“ㅏ”。它们可以是单独的字符并显示给用户,就像我在这里写的那样,您现在可以看到它们。但如果它们一起使用,它们会被渲染为一个字符“і”,而不是“ㄱㅏ”。

有两种方法可以表示韩文字符“і”:

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

大多数时候使用前者。后者很少被使用,说实话,我根本无法想象它什么时候被使用。 无论如何,第一个只是一个预先组合的字母,第二个是前导元音的序列,被视为一个字符。渲染后,它们看起来完全相同,并且实际上两者在规范上是等效的。 另外,以下行在 C# 中返回 true:

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

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

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

这是我的问题:

我在这里做错了什么吗?

与 ICU 不同,.NET 中的文本元素不是用户感知的字符?

最佳答案

这里的基本问题是根据韩国标准 KS X 1026 ,两个 jamos 与其组合形式 і 不同。事实上,官方标准中使用了这个确切的示例(参见第 6.2 节)。

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

您首先需要确保数据的格式正确(不太可能,因为事实上的标准是完全忽略官方标准的)否则您将需要使用 ICU(或类似的库)来处理这些情况。

关于c# - C#'s StringInfo and TextElementEnumerator can' t 正确识别字素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52423600/

相关文章:

java - C# 和 Java - 将文件从 Android 上传到 WCF

c++ - 在C++中将十进制转换为Unicode Char

java - 如何正确处理非英文字符?

regex - 如何在某些范围内使用 sed delete Unicode?

c# - winscard.dll 预热

c# - Form Builder On the fly 使用 asp.net mvc 站点

c# - 如何提供 "object"并将其传递给 viewmodelbase?

c - 在 C 中清空 char 字符串的最佳方法是什么?

java - 如何从 Java 字符串中删除除某些字符之外的所有字符?

java - 如何使用 Java 正确转义 awk 输入的字符串?