StringInfo и TextElementEnumerator в C# не могут правильно распознавать графемы
В C# StringInfo
а также TextElementEnumerator
классы предоставляют методы и свойства для текстовых элементов. И здесь мы можем найти определение текстового элемента.
.NET Framework определяет текстовый элемент как единицу текста, которая отображается в виде одного символа, то есть графемы. Текстовый элемент может быть любым из следующих:
Да, он говорит, что текстовый элемент - это графема в.NET. Я также тестировал некоторые символы Юникода, и это действительно казалось правдой, пока я не протестировал одну корейскую букву "가".
Как мы все знаем, некоторые символы Юникода состоят из нескольких кодовых точек. Также мы можем столкнуться с последовательностями кодовых точек, и именно поэтому я использую StringInfo
а также TextElementEnumerator
вместо простого String
,
StringInfo
а также TextElementEnumerator
мог бы сказать, если Char
s были суррогатными парами правильно. И "\u0061\u0308", символ Unicode, который состоит из нескольких кодовых точек, был распознан как один текстовый элемент, как и ожидалось. Но что касается "\u1100\u1161", он не смог сказать, что это был также один элемент текста.
"\ u1100" - это начальная буква "ㄱ", а "\u1161" - это гласная буква "ㅏ". Они могут быть отдельными персонажами и показываться пользователям так же, как я пишу здесь, и вы можете увидеть их сейчас. Но если они используются вместе, они отображаются как один символ "가" вместо "ㄱㅏ".
Существует два способа представления корейского символа "가":
- Использование единой кодовой точки U+AC00 от Hangul Syllable.
- Используя две кодовые точки U+1100 и U+1161 от Jamo.
Большую часть времени используется первый. Последний редко используется, если честно, я не могу себе представить, когда он вообще используется... В любом случае, первая - это просто одна предварительно составленная буква, а вторая - это последовательность Lead и Vowel, которая рассматривается как один символ. При визуализации они выглядят точно так же, и оба на самом деле канонически эквивалентны. Также следующая строка возвращает true в C#:
"\u1100\u1161".Normalize() == "\uAC00"
интересно, почему Normalize()
здесь прекрасно работает, когда C# не думает, что они являются одним целым текстовым элементом... Я думал, что это как-то связано с моей версией.NET, но оказывается, что это не так. Это происходит даже в Моно.
Я проверил это с ICU
а также, и он мог бы правильно трактовать "\ u1100 \ u1161" как одну графему! Я изначально думал StringInfo
а также TextElementEnumerator
может устранить необходимость в ICU4C в некоторых простых случаях, поэтому я очень разочарован..
Вот мой вопрос:
Я что-то здесь не так делаю?
или же
Текстовый элемент в.NET не воспринимается пользователем в отличие от ICU?
1 ответ
Основная проблема заключается в том, что в соответствии с корейским стандартом KS X 1026, два джемо ㄱ
а также ㅏ
отличаются от их комбинированной формы 가
, Фактически этот точный пример используется в официальном стандарте (см. Раздел 6.2).
Короче говоря, Microsoft пыталась следовать стандарту, но другие операционные системы и приложения не обязательно делают это. Следовательно, вы можете получить "искаженное" содержимое из другого программного обеспечения / платформ, которое, по-видимому, неправильно анализируется в Windows / в.NET, даже если оно анализируется "правильно" на этих платформах.
Вам нужно либо убедиться, что ваши данные в первую очередь правильно сформированы (маловероятно, учитывая, что де-факто стандарт должен полностью игнорировать официальный стандарт), либо вам придется использовать ICU (или аналогичную библиотеку) для решения этих проблем. случаев.