在 C# 中,StringInfo
和 TextElementEnumerator
类提供文本元素的方法和属性。
和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 字符由多个代码点组成。此外,我们可能会遇到代码点序列,这就是我使用 StringInfo
和 TextElementEnumerator
而不是简单的 String
的原因。
StringInfo
和 TextElementEnumerator
可以判断 Char
是否是正确的代理对。而“\u0061\u0308”,一种由多个代码点组成的 Unicode 字符,正如预期的那样被识别为一个文本元素。但至于“\u1100\u1161”,它并没有说它也是一个文本元素。
“\u1100”是前导字母“ㄱ”,“\u1161”是元音字母“ㅏ”。它们可以是单独的字符并显示给用户,就像我在这里写的那样,您现在可以看到它们。但如果它们一起使用,它们会被渲染为一个字符“і”,而不是“ㄱㅏ”。
有两种方法可以表示韩文字符“і”:
- 使用韩文音节中的单个代码点U+AC00。
- 使用 Jamo 中的两个代码点 U+1100 和 U+1161。
大多数时候使用前者。后者很少被使用,说实话,我根本无法想象它什么时候被使用。 无论如何,第一个只是一个预先组合的字母,第二个是前导和元音的序列,被视为一个字符。渲染后,它们看起来完全相同,并且实际上两者在规范上是等效的。 另外,以下行在 C# 中返回 true:
"\u1100\u1161".Normalize() == "\uAC00"
我想知道为什么当 C# 认为它们不是一个完整的文本元素时,这里的 Normalize()
工作得很好。
我以为这与我的.NET版本有关,但事实证明并非如此。即使在 Mono 中也会发生这种情况。
我也用 ICU
对此进行了测试,它可以正确将“\u1100\u1161”视为一个字素!
我最初认为 StringInfo
和 TextElementEnumerator
可以在某些简单情况下消除对 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/