UTF-16 - UTF-16
Язык (и) | Международный |
---|---|
Стандарт | Стандарт Юникода |
Классификация | Формат преобразования Unicode , кодирование переменной ширины |
Расширяется | UCS-2 |
Преобразует / кодирует | ISO 10646 ( Юникод ) |
UTF-16 ( 16-битный формат преобразования Unicode ) - это кодировка символов, способная кодировать все 1 112 064 действительных кодовых точки символов Unicode (на самом деле это количество кодовых точек продиктовано конструкцией UTF-16). Кодирование имеет переменную длину , поскольку кодовые точки кодируются с помощью одной или двух 16-битных кодовых единиц . UTF-16 возник из более ранней устаревшей 16-битной кодировки фиксированной ширины, теперь известной как UCS-2 (для 2-байтового универсального набора символов), когда стало ясно, что требуется более 2 16 (65 536) кодовых точек.
UTF-16 используется внутри таких систем, как Microsoft Windows , язык программирования Java и JavaScript / ECMAScript. Он также часто используется для обычного текста и файлов данных обработки текста в Microsoft Windows. Он редко используется для файлов в Unix-подобных системах. По состоянию на май 2019 года Microsoft изменила свой курс, сделав упор только на UTF-16 для Unicode; для приложений Windows Microsoft рекомендует и поддерживает UTF-8 (например, для приложений универсальной платформы Windows (UWP)).
UTF-16 - единственная веб-кодировка, несовместимая с ASCII , и никогда не завоевывала популярность в Интернете, где ее используют менее 0,002% (немногим более 1 тысячной 1 процента) веб-страниц. Для сравнения, UTF-8 используется на 97% всех веб-страниц. Hypertext Application Technology Рабочая группа Web (WHATWG) считает UTF-8 «обязательное кодирование для всех [текст]» и что по соображениям безопасности приложений браузер не должны использовать UTF-16.
История
В конце 1980-х годов началась работа по разработке единой кодировки для «универсального набора символов» ( UCS ), который заменит более ранние языковые кодировки единой скоординированной системой. Цель заключалась в том, чтобы включить все необходимые символы из большинства языков мира, а также символы из технических областей, таких как наука, математика и музыка. Первоначальная идея заключалась в том, чтобы заменить типичные 256-символьные кодировки, которые требовали 1 байт на символ, кодировкой с использованием 65 536 (2 16 ) значений, что потребовало бы 2 байта (16 бит) на символ.
Две группы работали над этим параллельно: ISO / IEC JTC 1 / SC 2 и Unicode Consortium , последний представлял в основном производителей компьютерного оборудования. Обе группы попытались синхронизировать свои назначения символов, чтобы развивающиеся кодировки были взаимно совместимы. Раннее двухбайтовое кодирование первоначально называлось «Unicode», но теперь называется «UCS-2».
Когда стало все более ясно, что 2 16 символов недостаточно, IEEE ввел большее 31-битное пространство и кодировку ( UCS-4 ), которая потребовала бы 4 байта на символ. Консорциум Unicode сопротивлялся этому как потому, что 4 байта на символ занимали много памяти и дискового пространства, так и потому, что некоторые производители уже вложили значительные средства в технологию 2 байта на символ. Схема кодирования UTF-16 была разработана как компромисс и представлена в версии 2.0 стандарта Unicode в июле 1996 года. Она полностью указана в RFC 2781, опубликованном в 2000 году IETF .
В кодировке UTF-16 кодовые точки меньше 2 16 кодируются одной 16-битной кодовой единицей, равной числовому значению кодовой точки, как в более старой UCS-2. Новые кодовые точки больше или равные 2 16 кодируются составным значением с использованием двух 16-битных кодовых единиц. Эти две 16-битные кодовые единицы выбираются из суррогатного диапазона UTF-16 0xD800–0xDFFF, который ранее не был назначен символам. Значения в этом диапазоне не используются как символы, и UTF-16 не предоставляет законного способа кодировать их как отдельные кодовые точки. Следовательно, поток UTF-16 состоит из одиночных 16-битных кодовых точек за пределами суррогатного диапазона для кодовых точек в базовой многоязычной плоскости (BMP) и пар 16-битных значений в суррогатном диапазоне для кодовых точек выше BMP.
UTF-16 указан в последних версиях как международного стандарта ISO / IEC 10646, так и стандарта Unicode. «UCS-2 теперь следует считать устаревшим. Он больше не относится к форме кодирования в 10646 или стандарте Unicode». С 2021 года нет планов по расширению UTF-16 для поддержки большего количества кодовых точек или кодовых точек, замененных суррогатами, поскольку это нарушит Политику стабильности Unicode в отношении общей категории или суррогатных кодовых точек. (Любая схема, которая остается самосинхронизирующимся кодом , потребует выделения как минимум одной кодовой точки BMP для запуска последовательности. Изменение цели кодовой точки запрещено.)
Описание
Каждая кодовая точка Unicode кодируется как одна или две 16-битные кодовые единицы . То, как эти 16-битные коды хранятся в виде байтов, зависит от " порядка байтов " текстового файла или протокола связи.
Для записи «символа» может потребоваться от двух до четырнадцати или даже более байтов. Например, символ флага эмодзи занимает 8 байтов, поскольку он «построен из пары скалярных значений Unicode» (и эти значения находятся за пределами BMP и требуют 4 байта каждое).
От U + 0000 до U + D7FF и от U + E000 до U + FFFF
И UTF-16, и UCS-2 кодируют кодовые точки в этом диапазоне как одиночные 16-битные кодовые единицы, которые численно равны соответствующим кодовым точкам. Эти кодовые точки в базовой многоязычной плоскости (BMP) являются единственными кодовыми точками, которые могут быть представлены в UCS-2. Начиная с Unicode 9.0, некоторые современные нелатинские азиатские, ближневосточные и африканские алфавиты выходят за пределы этого диапазона, как и большинство символов эмодзи .
Кодовые точки от U + 010000 до U + 10FFFF
Кодовые точки из других плоскостей (называемые дополнительными плоскостями ) кодируются как две 16-битные кодовые единицы, называемые суррогатной парой , по следующей схеме:
Низкий
Высокий
|
DC00 | DC01 | ... | DFFF |
---|---|---|---|---|
D800 | 010000 | 010001 | ... | 0103FF |
D801 | 010400 | 010401 | ... | 0107FF |
⋮ | ⋮ | ⋮ | ⋱ | ⋮ |
DBFF | 10FC00 | 10FC01 | ... | 10FFFF |
- 0x10000 вычитается из кодовой точки (U) , оставляя 20-битное число (U ') в диапазоне шестнадцатеричных чисел 0x00000–0xFFFFF. Обратите внимание, что для этих целей значение U не должно превышать 0x10FFFF.
- Старшие десять битов (в диапазоне 0x000–0x3FF) добавляются к 0xD800, чтобы получить первую 16-битную кодовую единицу или старший заменитель (W1) , который будет находиться в диапазоне 0xD800–0xDBFF .
- Младшие десять битов (также в диапазоне 0x000–0x3FF) добавляются к 0xDC00, чтобы получить вторую 16-битную кодовую единицу или младший суррогат (W2) , который будет находиться в диапазоне 0xDC00–0xDFFF .
Наглядно проиллюстрированное распределение U ' между W1 и W2 выглядит следующим образом:
U' = yyyyyyyyyyxxxxxxxxxx // U - 0x10000
W1 = 110110yyyyyyyyyy // 0xD800 + yyyyyyyyyy
W2 = 110111xxxxxxxxxx // 0xDC00 + xxxxxxxxxx
Высокие суррогатный и низкие суррогатный также известны как «ведущий» и «задняя» суррогаты, соответственно, аналогичные передние и задние байты UTF-8.
Поскольку диапазоны для высоких суррогатов ( 0xD800–0xDBFF ), низких суррогатов ( 0xDC00–0xDFFF ) и допустимых символов BMP (0x0000–0xD7FF, 0xE000–0xFFFF) не пересекаются , суррогат не может соответствовать символу BMP, или чтобы две соседние кодовые единицы выглядели как законная суррогатная пара . Это значительно упрощает поиск. Это также означает, что UTF-16 самосинхронизируется на 16-битных словах: может ли кодовая единица запускать символ, может быть определено без изучения более ранних кодовых единиц (т. Е. Тип кодовой единицы может быть определен диапазонами значений, в которых она падает). UTF-8 разделяет эти преимущества, но многие более ранние схемы многобайтового кодирования (такие как Shift JIS и другие азиатские многобайтовые кодировки) не допускали однозначного поиска и могли быть синхронизированы только путем повторного синтаксического анализа с начала строки (UTF -16 не является самосинхронизирующимся, если один байт потерян или если обход начинается со случайного байта).
Поскольку все наиболее часто используемые символы находятся в BMP, обработка суррогатных пар часто не проверяется тщательно. Это приводит к постоянным ошибкам и потенциальным дырам в безопасности даже в популярном и хорошо изученном прикладном программном обеспечении (например, CVE - 2008-2938 , CVE- 2012-2135 ).
В Дополнительных Плоскостях содержат эмодзи , исторические сценарии, менее часто используемые символы, меньше используемую китайскую идеограмму и т.д. Поскольку кодирование дополнительных плоскостей содержит 20 старших бит (10 из 16 бит в каждом из высоких и низких суррогатов ), 2 20 кодовых точек могут быть закодированы, разделены на 16 плоскостей по 2 16 кодовых точек в каждой. Включая отдельно управляемый базовый многоязычный самолет, всего 17 самолетов.
U + D800 в U + DFFF
Стандарт Unicode постоянно резервирует эти значения кодовых точек для кодирования UTF-16 суррогатов высокого и низкого уровня, и им никогда не будет назначен символ, поэтому не должно быть причин для их кодирования. Официальный стандарт Unicode говорит, что никакие формы UTF, включая UTF-16, не могут кодировать эти кодовые точки.
Однако UCS-2, UTF-8 и UTF-32 могут кодировать эти кодовые точки тривиальными и очевидными способами, и большое количество программного обеспечения это делает, даже несмотря на то, что в стандарте указано, что такие схемы следует рассматривать как ошибки кодирования.
Можно однозначно закодировать непарный суррогат (высокий суррогатный код, за которым не следует низкий, или низкий, без предшествующего высокого) в формате UTF-16, используя кодовую единицу, равную кодовой точке. . Результат не является допустимым UTF-16, но большинство реализаций кодировщика и декодера UTF-16 делают это тогда при преобразовании между кодировками. Windows позволяет использовать непарные суррогаты в именах файлов и других местах, что обычно означает, что они должны поддерживаться программным обеспечением, несмотря на то, что они исключены из стандарта Unicode.
Примеры
Чтобы закодировать U + 10437 (𐐷) в UTF-16:
- Вычтите 0x10000 из кодовой точки, оставив 0x0437.
- Для старшего суррогата сдвиньте вправо на 10 (разделите на 0x400), затем добавьте 0xD800, в результате получится 0x0001 + 0xD800 = 0xD801.
- Для младшего суррогата возьмите младшие 10 бит (остаток от деления на 0x400), затем добавьте 0xDC00, в результате получится 0x0037 + 0xDC00 = 0xDC37.
Чтобы декодировать U + 10437 (𐐷) из UTF-16:
- Возьмите старший суррогат (0xD801) и вычтите 0xD800, затем умножьте на 0x400, в результате получится 0x0001 × 0x400 = 0x0400.
- Возьмите младший суррогат (0xDC37) и вычтите 0xDC00, в результате получится 0x37.
- Сложите эти два результата вместе (0x0437) и, наконец, добавьте 0x10000, чтобы получить окончательную декодированную кодовую точку UTF-32, 0x10437.
В следующей таблице приведены данные об этом и других преобразованиях. Цвета показывают, как биты из кодовой точки распределяются между байтами UTF-16. Дополнительные биты, добавленные в процессе кодирования UTF-16, показаны черным.
Характер | Двоичный код | Двоичный UTF-16 | Единицы шестнадцатеричного кода UTF-16 |
Шестнадцатеричные байты UTF-16BE |
Шестнадцатеричные байты UTF-16LE |
|
---|---|---|---|---|---|---|
$ |
U+0024
|
0000 0000 0010 0100
|
0000 0000 0010 0100
|
0024
|
00 24
|
24 00
|
€ |
U+20AC
|
0010 0000 1010 1100
|
0010 0000 1010 1100
|
20AC
|
20 AC
|
AC 20
|
𐐷 |
U+10437
|
0001 0000 0100 0011 0111
|
1101 1000 0000 0001 1101 1100 0011 0111
|
D801 DC37
|
D8 01 DC 37
|
01 D8 37 DC
|
𤭢 |
U+24B62
|
0010 0100 1011 0110 0010
|
1101 1000 0101 0010 1101 1111 0110 0010
|
D852 DF62
|
D8 52 DF 62
|
52 D8 62 DF
|
Схемы кодирования байтового порядка
UTF-16 и UCS-2 создают последовательность из 16-битных кодовых единиц. Поскольку большинство протоколов связи и хранения определены для байтов, и каждый блок, таким образом, занимает два 8-битных байта, порядок байтов может зависеть от порядка байтов (порядка байтов) архитектуры компьютера.
Чтобы помочь в распознавании порядка байтов кодовых единиц, UTF-16 позволяет метке порядка байтов (BOM), кодовой точке со значением U + FEFF, предшествовать первому фактическому кодированному значению. (U + FEFF - это невидимый неразрывный пробел нулевой ширины / символ ZWNBSP.) Если конечная архитектура декодера совпадает с архитектурой кодера, декодер обнаруживает значение 0xFEFF, но декодер с обратным порядком байтов интерпретирует BOM как несимвольное значение U + FFFE зарезервировано для этой цели. Этот неверный результат дает подсказку для выполнения замены байтов для оставшихся значений.
Если спецификация отсутствует, RFC 2781 рекомендует использовать кодировку с прямым порядком байтов. На практике, из-за того, что Windows по умолчанию использует прямой порядок следования байтов, многие приложения предполагают обратную кодировку. Также надежно определять порядок байтов путем поиска нулевых байтов при условии, что символы меньше U + 0100 очень распространены. Если большее количество четных байтов (начиная с 0) равны нулю, то это обратный порядок байтов.
Стандарт также позволяет явно указывать порядок байтов, указывая UTF-16BE или UTF-16LE в качестве типа кодировки. Когда порядок байтов указан явно таким образом, спецификация специально не должна добавляться к тексту, а U + FEFF в начале следует обрабатывать как символ ZWNBSP. Большинство приложений игнорируют спецификации во всех случаях, несмотря на это правило.
Для интернет- протоколов IANA утвердила «UTF-16», «UTF-16BE» и «UTF-16LE» в качестве имен для этих кодировок (имена нечувствительны к регистру). Псевдонимы UTF_16 или UTF16 могут иметь значение в некоторых языках программирования или программных приложениях, но они не являются стандартными именами в Интернет-протоколах.
Подобные обозначения, UCS-2BE и UCS-2LE , используются для отображения версий UCS-2 .
использование
UTF-16 используется для текста в API ОС всех поддерживаемых в настоящее время версий Microsoft Windows (включая, по крайней мере, все, начиная с Windows CE / 2000 / XP / 2003 / Vista / 7 ), включая Windows 10 . В Windows XP код выше U + FFFF не входит ни в один шрифт, поставляемый с Windows для европейских языков. Старые системы Windows NT (до Windows 2000) поддерживают только UCS-2. Файлы и сетевые данные, как правило, представляют собой смесь кодировок UTF-16, UTF-8 и устаревших байтовых кодировок.
Хотя была некоторая поддержка UTF-8 даже для Windows XP, она была улучшена (в частности, возможность называть файл с использованием UTF-8) в инсайдерской сборке Windows 10 17035 и обновлении за апрель 2018 г., а по состоянию на май 2019 г. Microsoft рекомендует программное обеспечение. используйте его вместо UTF-16.
Я IBM операционная система определяет CCSID ( код страницы ) 13488 для UCS-2 кодирования и CCSID 1200 для UTF-16 кодировке, хотя система обрабатывает их обоих , как UTF-16.
UTF-16 используется операционными системами Qualcomm BREW ; в .NET среды; и набор инструментов кроссплатформенных графических виджетов Qt .
ОС Symbian, используемая в телефонах Nokia S60 и Sony Ericsson UIQ, использует UCS-2. Мобильные телефоны iPhone используют UTF-16 для службы коротких сообщений вместо UCS-2, описанного в стандартах 3GPP TS 23.038 ( GSM ) и IS-637 ( CDMA ).
Joliet файловой системы , используется в CD-ROM СМИ, кодирует имена файлов с использованием UCS-2be (до шестидесяти четырех символов Unicode в имени файла).
Python языковая среда официально использует только UCS-2 внутри , начиная с версии 2.0, но декодер UTF-8 «Unicode» производит правильно UTF-16. Начиная с Python 2.2, поддерживаются «широкие» сборки Unicode, которые вместо этого используют UTF-32; в основном они используются в Linux. Python 3.3 больше никогда не использует UTF-16, вместо этого кодировка, которая дает наиболее компактное представление для данной строки, выбирается из ASCII / Latin-1, UCS-2 и UTF-32.
Первоначально в Java использовался UCS-2, а в J2SE 5.0 добавлена поддержка дополнительных символов UTF-16 .
JavaScript может использовать UCS-2 или UTF-16. Начиная с ES2015, в язык были добавлены строковые методы и флаги регулярных выражений, которые позволяют обрабатывать строки с точки зрения независимого от кодирования.
Во многих языках строки в кавычках нуждаются в новом синтаксисе для цитирования символов, отличных от BMP, поскольку "\uXXXX"
синтаксис в стиле C явно ограничивает себя 4 шестнадцатеричными цифрами. Следующие примеры иллюстрируют синтаксис символа «𝄞», отличного от BMP (U + 1D11E, МУЗЫКАЛЬНЫЙ СИМВОЛ G CLEF). Наиболее распространенным (используемым C ++ , C # , D и некоторыми другими языками) является использование буквы «U» в верхнем регистре с 8 шестнадцатеричными цифрами, например "\U0001D11E"
. В регулярных выражениях Java 7, ICU и Perl "\x{1D11E}"
необходимо использовать синтаксис ; аналогично, в ECMAScript 2015 (JavaScript) escape-формат равен "\u{1D11E}"
. Во многих других случаях (например, Java вне регулярных выражений) единственный способ получить символы, отличные от BMP, - это ввести суррогатные половинки индивидуально, например: "\uD834\uDD1E"
для U + 1D11E.
Реализации строк, основанные на UTF-16, обычно определяют длину строки и позволяют индексацию в терминах этих 16-битных кодовых единиц , а не в терминах кодовых точек. Ни кодовые точки, ни кодовые единицы не соответствуют чему-либо, что конечный пользователь мог бы распознать как «символ»; то, что пользователи идентифицируют как символы, обычно может состоять из базовой кодовой точки и последовательности комбинируемых символов (или может быть последовательностью кодовых точек какого-либо другого типа, например, хангыль, соединяющий джамос) - Unicode называет эту конструкцию графемой cluster - и поэтому приложения, работающие со строками Unicode, независимо от кодировки, должны справляться с тем фактом, что это ограничивает их способность произвольно разделять и комбинировать строки.
UCS-2 также поддерживается языком PHP и MySQL.
Swift версии 5, предпочтительный язык приложений Apple, переключился с UTF-16 на UTF-8 в качестве предпочтительной кодировки.
Смотрите также
Примечания
использованная литература
внешние ссылки
- Очень короткий алгоритм определения суррогатной пары для любой кодовой точки
- Техническое примечание Unicode №12: UTF-16 для обработки
- Вопросы и ответы по Unicode: в чем разница между UCS-2 и UTF-16?
- Индекс имени символа Unicode
- RFC 2781 : UTF-16, кодировка ISO 10646
- документация java.lang.String, обсуждающая обработку суррогатов