UTF-16LE
UTF-16LE (от англ. Unicode Transformation Format, 16-bit, Little Endian) — это одна из схем кодирования символов стандарта Unicode, в которой каждый символ кодируется одним или двумя 16-битными словами (кодовыми единицами), а порядок байтов в этих словах — от младшего к старшему (little-endian). UTF-16LE является вариантом кодировки UTF-16, в котором явно задан порядок байтов, что позволяет однозначно интерпретировать последовательность байтов без использования метки порядка байтов (BOM). Кодировка широко применяется в операционных системах семейства Windows, в среде разработки Java, а также в некоторых форматах файлов, таких как RTF и XML.
История и стандартизация
Стандарт Unicode был разработан для унификации представления текстов на всех языках мира. Первоначально, в версии Unicode 1.0 (1991 год), использовалась 16-битная кодировка UCS-2, которая могла кодировать только символы из базовой многоязычной плоскости (BMP) — до 65 536 кодовых точек. Однако с ростом числа символов потребовалось расширение, и в 1996 году с выходом Unicode 2.0 была введена кодировка UTF-16, которая, в отличие от UCS-2, поддерживает суррогатные пары для кодирования символов за пределами BMP.
Стандарт UTF-16 был зафиксирован в документах ISO/IEC 10646 и Unicode Consortium. В нём предусмотрены два варианта порядка байтов: UTF-16BE (big-endian, от старшего к младшему) и UTF-16LE (little-endian). Выбор порядка байтов зависит от аппаратной платформы: процессоры архитектуры x86 и x86-64, используемые в большинстве персональных компьютеров, работают в режиме little-endian, поэтому UTF-16LE является наиболее распространённым вариантом в среде Windows.
Принцип кодирования
UTF-16LE кодирует каждый символ Unicode в виде последовательности 16-битных кодовых единиц (code units). Символы из базовой многоязычной плоскости (BMP), то есть с кодовыми точками от U+0000 до U+FFFF, кодируются одним 16-битным значением, равным их кодовой точке. Например, символ «A» (U+0041) в UTF-16LE представляется как 0x41 0x00 (младший байт 0x41, старший 0x00).
Символы, находящиеся за пределами BMP (кодовые точки от U+10000 до U+10FFFF), кодируются с помощью суррогатных пар. Для этого используется механизм, при котором кодовая точка вычитается из 0x10000, результат делится на 1024 (0x400), и к частному добавляется 0xD800 (старший суррогат), а к остатку — 0xDC00 (младший суррогат). Полученные два 16-битных значения записываются последовательно. Например, символ «𝄞» (U+1D11E) кодируется как 0xD834 0xDD1E (в little-endian порядке: 0x34 0xD8 0x1E 0xDD).
Порядок байтов
В UTF-16LE каждый 16-битный код хранится в памяти с младшим байтом первым, а старшим — вторым. Это означает, что для двухбайтового значения 0x1234 в файле или памяти сначала идёт байт 0x34, затем 0x12. Для суррогатных пар порядок байтов применяется к каждому из двух 16-битных слов независимо.
Метка порядка байтов (BOM)
Для различения UTF-16LE и UTF-16BE в начале текстового потока может использоваться метка порядка байтов (BOM) — символ U+FEFF (ZERO WIDTH NO-BREAK SPACE). В UTF-16LE этот символ кодируется как 0xFF 0xFE (в little-endian порядке). Однако в UTF-16LE использование BOM не является обязательным, так как порядок байтов уже задан названием кодировки. При чтении файла без BOM система должна заранее знать, что используется little-endian порядок.
Применение
Операционные системы Windows
UTF-16LE является основной кодировкой для текстовых строк в операционных системах Windows (начиная с Windows NT 3.1). Внутреннее представление строк в Windows API (функции семейства WideCharToMultiByte и MultiByteToWideChar) использует 16-битные символы в формате UTF-16LE. Файлы конфигурации, реестр Windows и многие системные компоненты (например, имена файлов в NTFS) хранятся в этой кодировке.
Среда Java
Виртуальная машина Java (JVM) использует UTF-16LE для внутреннего представления строк. Тип char в Java является 16-битным беззнаковым целым, и строки хранятся в виде массива char[] в кодировке UTF-16 (с порядком байтов, зависящим от платформы). Однако при передаче данных через сеть или файлы Java часто использует UTF-8, а UTF-16LE применяется в основном для совместимости с Windows.
Форматы файлов
Некоторые форматы файлов требуют или рекомендуют использование UTF-16LE. Например:
- RTF (Rich Text Format) — в спецификации RTF версии 1.9.1 и выше для кодирования символов за пределами ASCII рекомендуется UTF-16LE с BOM.
- XML — хотя по умолчанию XML-документы используют UTF-8, спецификация допускает использование UTF-16LE, если в начале файла указана соответствующая кодировка (например,
<?xml version="1.0" encoding="UTF-16LE"?>). - .NET Framework — строки в .NET (C#, VB.NET) хранятся в UTF-16LE, так как CLR (Common Language Runtime) использует ту же кодировку, что и Windows.
Веб-технологии
В веб-среде UTF-16LE используется редко, так как UTF-8 является стандартом де-факто для HTML и HTTP. Однако некоторые старые веб-страницы или API могут использовать UTF-16LE, особенно если они созданы для Windows-приложений.
Сравнение с другими кодировками
UTF-8
UTF-8 является более компактной для текстов на латинице и ASCII, так как каждый символ занимает от 1 до 4 байтов, а для ASCII — 1 байт. UTF-16LE, напротив, всегда использует минимум 2 байта на символ (для BMP), что делает его менее эффективным для английского текста, но более эффективным для языков, использующих кириллицу, арабскую вязь или иероглифы, где символы в UTF-8 занимают 2-3 байта, а в UTF-16LE — 2 байта.
UTF-16BE
UTF-16BE отличается от UTF-16LE только порядком байтов. Он используется в системах с big-endian архитектурой, таких как некоторые мейнфреймы IBM, PowerPC (до перехода на x86) и в сетевых протоколах (например, в Java-апплетах). UTF-16LE более распространён на платформах x86.
UCS-2
UCS-2 является устаревшей кодировкой, которая кодирует только символы BMP (до U+FFFF) и не поддерживает суррогатные пары. UTF-16LE полностью обратно совместима с UCS-2 для символов BMP, но для символов за пределами BMP требуется использование суррогатных пар, что делает UCS-2 непригодным для современных текстов.
Преимущества и недостатки
Преимущества
- Простота обработки — для символов BMP каждому символу соответствует ровно 2 байта, что упрощает индексацию и поиск.
- Эффективность для нелатинских алфавитов — кириллица, греческий, арабский, иврит и многие другие письменности занимают 2 байта на символ, что меньше, чем в UTF-8 (2-3 байта).
- Совместимость с Windows и Java — является нативной кодировкой для этих платформ.
Недостатки
- Избыточность для латиницы — каждый символ ASCII занимает 2 байта, что вдвое больше, чем в UTF-8.
- Проблемы с суррогатными парами — символы за пределами BMP (например, редкие иероглифы или эмодзи) кодируются двумя 16-битными словами, что усложняет обработку строк (например, длина строки в символах не равна числу 16-битных единиц).
- Зависимость от порядка байтов — при передаче данных между системами с разным порядком байтов требуется преобразование или явное указание BOM.
Примеры
Пример кодирования строки «Привет» в UTF-16LE:
- Символы: П (U+041F), р (U+0440), и (U+0438), в (U+0432), е (U+0435), т (U+0442).
- В little-endian порядке: 0x1F 0x04, 0x40 0x04, 0x38 0x04, 0x32 0x04, 0x35 0x04, 0x42 0x04.
- В байтовом представлении: 1F 04 40 04 38 04 32 04 35 04 42 04.
Пример с суррогатной парой для символа «😀» (U+1F600):
- Вычисление: 0x1F600 - 0x10000 = 0xF600; 0xF600 / 0x400 = 0x3D (старший суррогат: 0xD800 + 0x3D = 0xD83D); остаток: 0xF600 % 0x400 = 0x200 (младший суррогат: 0xDC00 + 0x200 = 0xDE00).
- В little-endian: 0x3D 0xD8 0x00 0xDE (4 байта).
Интересные факты
- В Windows-1251 и других однобайтовых кодировках кириллица занимает 1 байт, но в UTF-16LE — 2 байта, что делает UTF-16LE менее эффективным для русского текста по сравнению с однобайтовыми кодировками, но более универсальным.
- Спецификация Unicode рекомендует использовать UTF-8 для новых протоколов и форматов, но UTF-16LE остаётся стандартом для внутреннего представления в Windows.
- В файловой системе NTFS имена файлов хранятся в UTF-16LE, что позволяет использовать символы из любых языков, включая иероглифы и эмодзи.
Источники
- Unicode Consortium. The Unicode Standard, Version 15.0. — 2022.
- ISO/IEC 10646:2020. Information technology — Universal coded character set (UCS).
- RFC 2781. UTF-16, an encoding of ISO 10646. — 2000.
- Microsoft. Windows Data Types for Strings. — MSDN documentation.
- Gosling J., Joy B., Steele G., Bracha G. The Java Language Specification, Java SE 17 Edition. — 2021.
BFOmetr — база данных и аналитика по компаниям России.
На главную BFOmetr →