Подтвердить что ты не робот

Как создать строку с суррогатной парой внутри нее?

Я видел этот пост в блоге Jon Skeet, где он рассказывает о перестановке строк. Я хотел попробовать пример, который он показал, но, похоже, это работает..., что заставляет меня поверить, что я понятия не имею, как создать строку, содержащую суррогатную пару, которая фактически приведет к сбою строки. Как на самом деле происходит создание строки с суррогатной парой в ней, чтобы я мог сам увидеть ошибку?

4b9b3361

Ответ 1

Термин "суррогатная пара" относится к средству кодирования символов Unicode с высокими кодовыми точками в UTF-16 схемы кодирования (см noreferrer этой странице для получения дополнительной информации);

В символьной кодировке Unicode символы отображаются в значениях между 0x000000 и 0x10FFFF. Внутри схема кодирования UTF-16 используется для хранения строк текста Unicode, в которых рассматриваются двухбайтовые (16-bit) кодовые последовательности. Поскольку два байта могут содержать только диапазон символов от 0x0000 до 0xFFFF, для хранения значений выше этого диапазона (0x010000 - 0x10FFFF) используется дополнительная сложность.

Это делается с использованием пар кодовых точек, известных как суррогаты. Суррогатные символы классифицируются в двух разных диапазонах, известных как low surrogates и high surrogates, в зависимости от того, разрешены ли они в начале или в конце двухкодовой последовательности.

Попробуйте сами:

String surrogate = "abc" + Char.ConvertFromUtf32(Int32.Parse("2A601", NumberStyles.HexNumber)) + "def";

Char[] surrogateArray = surrogate.ToCharArray();
Array.Reverse(surrogateArray);

String surrogateReversed = new String(surrogateArray);

или это, если вы хотите придерживаться примера блога:

String surrogate = "Les Mise" + Char.ConvertFromUtf32(Int32.Parse("0301", NumberStyles.HexNumber)) + "rables";

Char[] surrogateArray = surrogate.ToCharArray();
Array.Reverse(surrogateArray);

String surrogateReversed = new String(surrogateArray);

nnd затем проверьте строковые значения с помощью отладчика. Джон Скит чертовски прав... строки и даты кажутся легкими, но они абсолютно НЕ.

Ответ 2

Самый простой способ - использовать \U########, где U является капиталом, а # обозначает ровно восемь шестнадцатеричных цифр. Если значение превышает 0000FFFF шестнадцатеричное число, потребуется суррогатная пара:

string myString = "In the game of mahjong \U0001F01C denotes the Four of circles";

Вы можете проверить myString.Length, чтобы увидеть, что один символ Юникода занимает два значения .NET Char. Обратите внимание, что тип Char имеет пару методов static, которые помогут вам определить, является ли Char частью суррогатной пары.

Если вы используете язык .NET, который не имеет что-то вроде escape-последовательности \U########, вы можете использовать метод ConvertFromUtf32, например:

string fourCircles = char.ConvertFromUtf32(0x1F01C);

Дополнение: Если ваш исходный файл С# имеет кодировку, которая позволяет всем символам Юникода, например UTF-8, вы можете просто поместить charater непосредственно в файл (путем копирования-вставки). Например:

string myString = "In the game of mahjong 🀜 denotes the Four of circles";

Символ UTF-8 кодируется в исходном файле (в моем примере), но будет кодироваться UTF-16 (суррогатные пары), когда приложение запускается, а строка - в памяти.

(Не уверен, что программа Qaru корректно обрабатывает мой маджонг. Попробуйте нажать "отредактировать" на этот ответ и скопировать-вставить из текста там, если "смешной" символ здесь отсутствует.)