C# 的 StringInfo 和 TextElementEnumerator 无法正确识别字形
C#'s StringInfo and TextElementEnumerator can't recognize graphemes properly
在 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”是元音字母“ㅏ”。它们可以是单独的字符,就像我在这里写的那样显示给用户,你现在可以看到它们。但如果它们一起使用,它们将被渲染为一个字符“가”而不是“ㄱㅏ”。
韩文“가”的表示方法有两种:
- 使用 Hangul Syllable.
中的单个代码点 U+AC00
- 使用来自 Jamo 的两个代码点 U+1100 和 U+1161。
大多数情况下使用前者。后者很少用到,老实说,我根本无法想象它什么时候被用到。。
无论如何,第一个只是一个预组合字母,第二个是 Lead 和 Vowel 的序列,被视为一个字符。渲染时它们看起来完全一样,实际上两者在规范上是等价的。
此外,C# 中的以下行 returns 为真:
"\u1100\u1161".Normalize() == "\uAC00"
我想知道为什么 Normalize()
在 C# 认为它们不是一个完整的文本元素时在这里工作得很好..
我认为这与我的 .NET 版本有关,但事实并非如此。即使在 Mono 中也会发生这种情况。
我也用 ICU
测试了它,它可以将“\u1100\u1161”视为一个字素正确!
我最初认为 StringInfo
和 TextElementEnumerator
可以在一些简单的情况下消除对 ICU4C 的需求,所以我现在很失望..
这是我的问题:
我是不是做错了什么?
或
与 ICU 不同,.NET 中的文本元素不是用户感知的字符?
这里的基本问题是,根据韩国标准 KS X 1026,两个 jamos ㄱ
和 ㅏ
不同于它们的组合形式 가
。事实上,官方标准中使用了这个确切的示例(请参阅第 6.2 节)。
长话短说,Microsoft 试图遵循该标准,但其他操作系统和应用程序不一定这样做。因此,您可以从其他软件/平台获取 "malformed" 内容,这些内容似乎在 Windows / 在 .NET 中被错误解析,即使它在这些平台上被解析 "correctly" 也是如此。
您首先需要确保您的数据格式正确(不太可能,因为 事实上的 标准是完全忽略 官方标准)或者你需要使用ICU(或类似的库)来处理这些情况。
在 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”是元音字母“ㅏ”。它们可以是单独的字符,就像我在这里写的那样显示给用户,你现在可以看到它们。但如果它们一起使用,它们将被渲染为一个字符“가”而不是“ㄱㅏ”。
韩文“가”的表示方法有两种:
- 使用 Hangul Syllable. 中的单个代码点 U+AC00
- 使用来自 Jamo 的两个代码点 U+1100 和 U+1161。
大多数情况下使用前者。后者很少用到,老实说,我根本无法想象它什么时候被用到。。 无论如何,第一个只是一个预组合字母,第二个是 Lead 和 Vowel 的序列,被视为一个字符。渲染时它们看起来完全一样,实际上两者在规范上是等价的。 此外,C# 中的以下行 returns 为真:
"\u1100\u1161".Normalize() == "\uAC00"
我想知道为什么 Normalize()
在 C# 认为它们不是一个完整的文本元素时在这里工作得很好..
我认为这与我的 .NET 版本有关,但事实并非如此。即使在 Mono 中也会发生这种情况。
我也用 ICU
测试了它,它可以将“\u1100\u1161”视为一个字素正确!
我最初认为 StringInfo
和 TextElementEnumerator
可以在一些简单的情况下消除对 ICU4C 的需求,所以我现在很失望..
这是我的问题:
我是不是做错了什么?
或
与 ICU 不同,.NET 中的文本元素不是用户感知的字符?
这里的基本问题是,根据韩国标准 KS X 1026,两个 jamos ㄱ
和 ㅏ
不同于它们的组合形式 가
。事实上,官方标准中使用了这个确切的示例(请参阅第 6.2 节)。
长话短说,Microsoft 试图遵循该标准,但其他操作系统和应用程序不一定这样做。因此,您可以从其他软件/平台获取 "malformed" 内容,这些内容似乎在 Windows / 在 .NET 中被错误解析,即使它在这些平台上被解析 "correctly" 也是如此。
您首先需要确保您的数据格式正确(不太可能,因为 事实上的 标准是完全忽略 官方标准)或者你需要使用ICU(或类似的库)来处理这些情况。