Как создать строку с суррогатной парой внутри нее?
Я видел этот пост в блоге Jon Skeet, где он рассказывает о перестановке строк. Я хотел попробовать пример, который он показал, но, похоже, это работает..., что заставляет меня поверить, что я понятия не имею, как создать строку, содержащую суррогатную пару, которая фактически приведет к сбою строки. Как на самом деле происходит создание строки с суррогатной парой в ней, чтобы я мог сам увидеть ошибку?
Ответы
Ответ 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 корректно обрабатывает мой маджонг. Попробуйте нажать "отредактировать" на этот ответ и скопировать-вставить из текста там, если "смешной" символ здесь отсутствует.)