Являются ли суррогатные пары единственным способом представления кодовых точек размером более 2 байтов в UTF-16?
Я знаю, что это, вероятно, глупый вопрос, но я должен быть уверен в этом вопросе. Поэтому мне нужно знать, например, говорит ли язык программирования, что его тип String использует кодировку UTF-16, означает ли это:
- он будет использовать 2 байта для кодовых точек в диапазоне от U+0000 до U+FFFF.
- он будет использовать суррогатные пары для кодовых точек, превышающих U+FFFF (4 байта на кодовую точку).
Или некоторые языки программирования используют свои собственные "трюки" при кодировании и не соблюдают этот стандарт на 100%.
2 ответа
UTF-16- это заданная кодировка, поэтому, если вы "используете UTF-16", вы делаете то, что он говорит, и не изобретаете никаких собственных "уловок".
Я бы не стал говорить о "двух байтах" так, как вы. Это деталь. Ключевая часть UTF-16 заключается в том, что вы кодируете кодовые точки как последовательность 16-битных кодовых блоков, а пары суррогатов используются для кодирования кодовых точек, больших 0xFFFF. Тот факт, что одна кодовая единица состоит из двух 8-битных байтов, является вторым уровнем детализации, который применяется ко многим системам (но есть системы с большими размерами байтов, где это не имеет значения), и в этом случае вы можете различать большие - и представления с прямым порядком байтов.
Но если смотреть в другую сторону, нет абсолютно никаких причин, по которым вам следует использовать именно UTF-16. В конечном счете, текст Unicode - это просто последовательность чисел (до 221), и вам решать, как их представлять и сериализовать.
Я бы с радостью привел довод, что UTF-16- это историческая авария, которую мы, вероятно, не сделали бы, если бы нам пришлось все сейчас переделывать: это кодировка переменной длины, такая же, как UTF-8, поэтому вы не получаете произвольного доступа, в отличие от UTF-32, но это также многословно. Он страдает от проблем с порядком байтов, в отличие от UTF-8. Хуже всего то, что он путает части стандарта Unicode с внутренним представлением, используя фактические значения кодовых точек для суррогатных пар.
Единственная причина (по моему мнению), что UTF-16 существует, состоит в том, что в какой-то ранний момент люди полагали, что 16 бит будет достаточно для всего человечества навсегда, и поэтому предполагалось, что UTF-16 будет окончательным решением (как UTF-32 сегодня). Когда это оказалось неправдой, суррогаты и более широкие диапазоны были добавлены в UTF-16. Сегодня вам в общем случае следует использовать UTF-8 для внешней сериализации или UTF-32 для эффективного доступа изнутри. (Могут быть дополнительные причины для предпочтения UCS-2 для чисто азиатского текста.)
UTF-16 сам по себе является стандартным. Однако большинство языков, строки которых основаны на 16-битных единицах кода (независимо от того, заявляют они или нет "поддерживают" UTF-16), могут использовать любую последовательность единиц кода, включая недопустимые суррогаты. Например, это обычно допустимый строковый литерал:
"x \uDC00 y \uD800 z"
и обычно вы получаете ошибку только при попытке записать ее в другую кодировку.
Необязательный параметр кодирования / декодирования в Python surrogateescape
использует такие недопустимые суррогаты для контрабанды токенов, представляющих отдельные байты 0x80–0xFF, в отдельные единицы суррогатного кода U+DC80–U+DCFF, в результате чего получается такая строка. Обычно это используется только внутри, поэтому вы вряд ли встретите это в файлах или в сети; и это относится только к UTF-16 в той же степени, что и Python str
Тип данных основан на 16-битных единицах кода (то есть на "узких" сборках между 3,0 и 3,3).
Мне не известны какие-либо другие часто используемые расширения / варианты UTF-16.