Saltar al contenido principal
Codificación de anchura variable de 16 bits Unicode Standard 17.0 §3.8 & §3.9 RFC 2781

Codificación UTF-16

UTF-16 (formato de transformación Unicode de 16 bits) es la codificación de caracteres de anchura variable que representa los valores escalares de Unicode mediante una o dos unidades de código de 16 bits (2 o 4 bytes). Los caracteres del Plano Multilingüe Básico (U+0000 a U+D7FF y U+E000 a U+FFFF) se mapean directamente a una sola unidad de 16 bits. Los caracteres de los planos suplementarios (U+10000 a U+10FFFF)—incluidos los emojis, los alfanuméricos matemáticos y las escrituras históricas—se codifican mediante un par ordenado de unidades de código reservadas llamado par sustituto.

Datos técnicos rápidos

Tamaño de unidad de código 16-bit Code Units (2 Bytes) Unidad fundamental de la forma de codificación
Unidades por valor escalar 1 or 2 Code Units (2 or 4 Bytes) 1 unidad para el BMP; 2 unidades para los suplementarios
Plano Multilingüe Básico (BMP) U+0000–U+D7FF & U+E000–U+FFFF Mapeo escalar directo 1:1 (1 unidad, 2 bytes)
Sustitutos reservados U+D800–U+DFFF 2,048 unidades reservadas; no son caracteres escalares
Planos suplementarios (1–16) U+10000–U+10FFFF Codificados como pares sustitutos (2 unidades, 4 bytes)
Endianness / orden de bytes UTF-16BE / UTF-16LE Serialización big-endian o little-endian
Marca de orden de bytes (BOM) Opcional (U+FEFF) BE: FE FF | LE: FF FE
Base de estándares Unicode 17.0 §3.8, §3.9 Table 3-5 / RFC 2781 Estándar del Unicode Consortium y del IETF

Espacio de código y distribución de rangos en UTF-16

El estándar Unicode divide todo el espacio de $1,114,112$ puntos de código en planos. UTF-16 gestiona los puntos de código con unidades de 16 bits simples para los caracteres escalares del BMP y con pares de unidades de 16 bits para los caracteres suplementarios, de acuerdo con la tabla 3-5 del estándar Unicode 17.0.

Plano de caracteres Rango escalar Unidades de código Longitud en bytes Rango de unidades de código (hex) Estado de codificación
Basic Multilingual Plane (BMP, Lower)
Covers ASCII, Latin, Greek, Cyrillic, Hebrew, Arabic, and most common scripts.
U+0000–U+D7FF 1 Unidad 2 Bytes 0000–D7FF Single Code Unit (Direct 1:1 scalar mapping)
High-Surrogate Range (Lead Surrogates)
Permanently reserved for the leading unit of a surrogate pair. Cannot stand alone.
U+D800–U+DBFF 1 Unidad 2 Bytes D800–DBFF Reserved High Surrogates (Not Scalar Values)
Low-Surrogate Range (Trail Surrogates)
Permanently reserved for the trailing unit of a surrogate pair. Cannot stand alone.
U+DC00–U+DFFF 1 Unidad 2 Bytes DC00–DFFF Reserved Low Surrogates (Not Scalar Values)
Basic Multilingual Plane (BMP, Upper)
Private Use Area, CJK compatibility, alphabetic presentation forms, specials.
U+E000–U+FFFF 1 Unidad 2 Bytes E000–FFFF Single Code Unit (Direct 1:1 scalar mapping)
Supplementary Planes (Planes 1–16)
Contains emojis, historic scripts (Linear B, Egyptian Hieroglyphs), musical notation, rare CJK ideographs.
U+10000–U+10FFFF 2 Unidades 4 Bytes D800 DC00 – DBFF DFFF Surrogate Pair Required (High Surrogate + Low Surrogate)

El mecanismo del par sustituto

Como una sola unidad de código de 16 bits puede direccionar como máximo $65,536$ valores, Unicode reservó $2,048$ unidades de código en el Plano Multilingüe Básico (plano 0) específicamente para codificar los $1,048,576$ caracteres suplementarios (planos 1–16).

Anatomía de un par sustituto (ejemplo: 😀 U+1F600) 2 unidades de código = 4 bytes = 1 carácter Unicode
Sustituto alto (inicial)
D83D
Rango: 0xD800–0xDBFF
Codifica los 10 bits altos ($0\text{x}03\text{D}$)
+
Sustituto bajo (final)
DE00
Rango: 0xDC00–0xDFFF
Codifica los 10 bits bajos ($0\text{x}200$)
=
Carácter Unicode decodificado
😀
U+1F600
Grinning Face (1 valor escalar)

1. Fórmula de codificación (escalar a sustitutos)

Para cualquier punto de código suplementario $C$ donde $0\text{x}10000 \le C \le 0\text{x}10\text{FFFF}$:

U' = C - 0x10000;
HighSurrogate = 0xD800 + (U' >> 10);
LowSurrogate = 0xDC00 + (U' & 0x3FF);

Restar $0\text{x}10000$ produce un número de 20 bits ($2^{20} = 1,048,576$). Dividirlo en dos mitades de 10 bits encaja perfectamente en las dos ventanas sustitutas de 1,024 unidades.

2. Fórmula de decodificación (sustitutos a escalar)

Dado un sustituto alto válido $W_1$ y un sustituto bajo $W_2$:

C = 0x10000 + ((W1 - 0xD800) << 10) + (W2 - 0xDC00);

Invierte los desplazamientos de 10 bits y suma el desplazamiento $0\text{x}10000$ para reconstruir el valor escalar Unicode exacto de 21 bits.

Inspector y validador interactivo de UTF-16

Explore en vivo la codificación de unidades de código UTF-16, alterne entre las serializaciones de bytes big-endian y little-endian, o introduzca unidades de código hexadecimales en bruto para validar la conformidad de las secuencias.

Preajustes rápidos:
Formato de visualización:
Puntos de código: 1
Unidades de código UTF-16: 2
Bytes serializados: 4
Grupos de grafemas: 1
Unidades de código UTF-16 en hexadecimal:
D83D DE00
😀 U+1F600
Plano Suplementario Multilingüe Par sustituto requerido
Sustituto alto: D83D
Sustituto bajo: DE00
Bytes BE: D8 3D DE 00
Bytes LE: 3D D8 00 DE

Ejemplo resuelto: codificación de 😀 (U+1F600)

Siga la derivación matemática y de desplazamiento de bits exacta definida por el estándar Unicode 17.0 para convertir el valor escalar suplementario U+1F600 en su par sustituto UTF-16 D83D DE00.

Paso 1
Subtract 0x10000
0x1F600 - 0x10000 = 0x0F600
Subtracting the base 0x10000 reduces the code point to a 20-bit value (0x00000..0xFFFFF).
Paso 2
Extract High & Low 10 Bits
High 10 bits: 0x03D (0000111101) | Low 10 bits: 0x200 (1000000000)
Split the 20-bit offset into two 10-bit values (0 to 1023 each).
Paso 3
Add High Surrogate Base (0xD800)
0xD800 + 0x03D = 0xD83D
The high (leading) surrogate unit is computed by adding the top 10 bits to 0xD800.
Paso 4
Add Low Surrogate Base (0xDC00)
0xDC00 + 0x200 = 0xDE00
The low (trailing) surrogate unit is computed by adding the lower 10 bits to 0xDC00.
Paso 5
Surrogate Pair Result
D83D DE00
Together, the ordered pair <0xD83D, 0xDE00> represents U+1F600 in UTF-16.

Verificación por decodificación inversa

C = 0x10000 + ((0xD83D - 0xD800) << 10) + (0xDE00 - 0xDC00)
C = 0x10000 + (0x03D × 1024) + 0x200 = 0x10000 + 0xF400 + 0x200 = 0x1F600 (U+1F600) ✓

La fórmula inversa reconstruye el valor escalar original con una fidelidad matemática del 100 %.

Ejemplos representativos de todos los planos

Caracteres Unicode representativos, símbolos matemáticos, escrituras históricas, marcas combinantes y secuencias complejas de emojis codificadas en UTF-16.

A

Latin Capital Letter A

ASCII / Basic Latin
Unidades de código UTF-16: 0041
Bytes serializados BE: 00 41
Bytes serializados LE: 41 00
1 Código Unidad 2 Bytes 1 Punto de código

1 code unit (2 bytes). Illustrates 16-bit BMP encoding where high byte is 0x00.

é

Latin Small Letter E with Acute

Latin-1 Supplement
Unidades de código UTF-16: 00E9
Bytes serializados BE: 00 E9
Bytes serializados LE: E9 00
1 Código Unidad 2 Bytes 1 Punto de código

1 code unit (2 bytes). Precomposed BMP accented character.

Euro Sign

Currency Symbols
Unidades de código UTF-16: 20AC
Bytes serializados BE: 20 AC
Bytes serializados LE: AC 20
1 Código Unidad 2 Bytes 1 Punto de código

1 code unit (2 bytes). Common BMP business character (0x20AC).

Infinity

Mathematical Operators
Unidades de código UTF-16: 221E
Bytes serializados BE: 22 1E
Bytes serializados LE: 1E 22
1 Código Unidad 2 Bytes 1 Punto de código

1 code unit (2 bytes). BMP mathematical symbol (0x221E).

😀

Grinning Face

Emoji / SMP
Unidades de código UTF-16: D83D DE00
Bytes serializados BE: D8 3D DE 00
Bytes serializados LE: 3D D8 00 DE
2 Código Unidades 4 Bytes 1 Punto de código

2 code units (4 bytes). Canonical emoji surrogate pair: D83D DE00.

𐂃

Linear B Ideogram B105F Mare

Historic Scripts (SMP)
Unidades de código UTF-16: D800 DC83
Bytes serializados BE: D8 00 DC 83
Bytes serializados LE: 00 D8 83 DC
2 Código Unidades 4 Bytes 1 Punto de código

2 code units (4 bytes). Tests high surrogate lower boundary (0xD800).

𪚥

CJK Unified Ideographs Extension B

Rare CJK Ideograph (SIP)
Unidades de código UTF-16: D869 DEA5
Bytes serializados BE: D8 69 DE A5
Bytes serializados LE: 69 D8 A5 DE
2 Código Unidades 4 Bytes 1 Punto de código

2 code units (4 bytes). Plane 2 Ideograph: U+2A6A5 -> D869 DEA5.

Combining E + Acute Accent

Combining Sequence
Unidades de código UTF-16: 0065 0301
Bytes serializados BE: 00 65 03 01
Bytes serializados LE: 65 00 01 03
2 Código Unidades 4 Bytes 2 Puntos de código

2 code points, 2 code units (4 bytes). 1 perceived glyph = 2 code units.

👩‍💻

Woman Technologist

ZWJ Emoji Sequence
Unidades de código UTF-16: D83D DC69 200D D83D DCBB
Bytes serializados BE: D8 3D DC 69 20 0D D8 3D DC BB
Bytes serializados LE: 3D D8 69 DC 0D 20 3D D8 BB DC
5 Código Unidades 10 Bytes 3 Puntos de código

3 code points, 5 UTF-16 code units (10 bytes). Complex sequence joined by ZWJ.

Orden de bytes y serialización: UTF-16BE frente a UTF-16LE

UTF-16 define una forma de codificación mediante unidades de código de 16 bits. Cuando estos enteros de 16 bits se serializan en un flujo de bytes de 8 bits (para transmisión por red o almacenamiento), el orden de los dos bytes dentro de cada unidad de código lo gobierna el esquema de codificación: big-endian o little-endian.

Carácter Punto de código Unidades de código de 16 bits UTF-16BE (big-endian) UTF-16LE (little-endian) Comportamiento de serialización
A U+0041 0041 00 41 41 00 ASCII: Big-Endian places 00 first; Little-Endian places 41 first.
U+20AC 20AC 20 AC AC 20 Euro Sign: Single code unit 20AC inverted in Little-Endian.
U+221E 221E 22 1E 1E 22 Infinity: Single code unit 221E inverted in Little-Endian.
😀 U+1F600 D83D DE00 D8 3D DE 00 3D D8 00 DE Emoji: Note that each 16-bit code unit is byte-swapped individually!
𐂃 U+10083 D800 DC83 D8 00 DC 83 00 D8 83 DC Historic script: D800 DC83 serialized to 00 D8 83 DC in Little-Endian.

Nota importante sobre el intercambio de sustitutos

Al serializar un par sustituto en modo little-endian (UTF-16LE), cada unidad de código de 16 bits se intercambia por bytes individualmente. El orden de las dos unidades de código no cambia: el sustituto alto precede siempre al sustituto bajo. Por ejemplo, D83D DE00 se convierte en 3D D8 00 DE, NO en 00 DE 3D D8.

Semántica de la marca de orden de bytes (BOM)

La marca de orden de bytes (BOM) es el carácter Unicode U+FEFF (ZERO WIDTH NO-BREAK SPACE). Colocada al principio de un flujo UTF-16 serializado, su patrón de bytes revela de inmediato si el flujo es big-endian o little-endian.

Firma UTF-16BE
FE FF

El byte de orden superior 0xFE precede al byte de orden inferior 0xFF. Señala un orden de bytes big-endian.

Firma UTF-16LE
FF FE

El byte de orden inferior 0xFF precede al byte de orden superior 0xFE. Señala un orden de bytes little-endian.

Contexto del flujo Estado del requisito Explicación según los estándares
Explicitly Labeled Streams (e.g. charset=utf-16le or utf-16be) Optional / Not Required When the MIME type or transport layer explicitly declares the endianness, the byte order is already known.
Generic "UTF-16" Byte Streams (without BE/LE designation) Recommended for Detection If labeled simply "UTF-16", an initial BOM identifies whether the stream is Big-Endian (FE FF) or Little-Endian (FF FE).
Generic "UTF-16" Streams Lacking a BOM Default to Big-Endian Per RFC 2781 Section 4.3, in the absence of a BOM, systems without prior agreement should interpret generic UTF-16 as Big-Endian (UTF-16BE).
Mid-Stream Occurrence of U+FEFF Treated as Zero-Width No-Break Space If U+FEFF appears after the stream header, it is treated as a non-breaking space character, though U+2060 (Word Joiner) is preferred.

El mito del requisito universal

UTF-16 NO exige universalmente un BOM. Aunque es habitual en los archivos de texto de Windows (como los .txt del Bloc de notas etiquetados "Unicode"), los protocolos que especifican charset=utf-16le o charset=utf-16be no requieren explícitamente un BOM. En las aplicaciones web, el estándar de codificación del WHATWG se basa en UTF-8, pero decodifica los flujos etiquetados como UTF-16 según el BOM explícito o las definiciones MIME.

Buena formación y secuencias sustitutas mal formadas

Una secuencia de unidades de código UTF-16 está bien formada si y solo si cada unidad sustituta aparece como parte de una secuencia correctamente emparejada y ordenada. Cualquier sustituto aislado o desemparejado infringe el estándar Unicode 17.0 §3.9 (definición D92).

Invariantes de conformidad de Unicode

  • Regla 1 (escalares del BMP): las unidades de código de 16 bits simples deben caer en U+0000..U+D7FF o U+E000..U+FFFF.
  • Regla 2 (sustitutos altos): a todo sustituto alto (0xD800..0xDBFF) debe seguirle inmediatamente un sustituto bajo (0xDC00..0xDFFF).
  • Regla 3 (sustitutos bajos): a todo sustituto bajo (0xDC00..0xDFFF) debe precederle inmediatamente un sustituto alto (0xD800..0xDBFF).
  • Regla 4 (no caracteres): los no caracteres (como U+FDD0..U+FDEF, U+FFFE, U+FFFF) son valores escalares Unicode válidos y nunca deben tratarse como errores de sustitutos.
Unidades de código (hex) Clasificación del error Desplazamiento del error Diagnóstico de conformidad estándar Riesgo de seguridad y del analizador
D800 UNPAIRED_HIGH_SURROGATE Posición 0 Isolated High Surrogate at end of sequence with no matching low surrogate. String truncation vulnerability; decoders may discard or generate replacement characters (U+FFFD).
D83D 0041 EXPECTED_LOW_SURROGATE Posición 1 High surrogate (D83D) followed by ASCII letter A (0041) instead of a low surrogate (DC00..DFFF). Surrogate desynchronization; downstream parsers may misinterpret payload boundaries.
DC00 UNPAIRED_LOW_SURROGATE Posición 0 Isolated Low Surrogate encountered without a preceding high surrogate. Orphaned trailing surrogate; causes malformed string crashes in strict environments.
DC00 D83D UNPAIRED_LOW_SURROGATE Posición 0 Inverted surrogate order: low surrogate (DC00) appears before high surrogate (D83D). Surrogate inversion produces two ill-formed code units; rejected by standard decoders.
D800 D800 EXPECTED_LOW_SURROGATE Posición 1 Two consecutive high surrogates; the first high surrogate is never completed. Surrogate stacking error; common when slice operations cut strings through surrogate boundaries.
0041 D83D TRUNCATED_SURROGATE_PAIR Posición 1 Valid ASCII A (0041) followed by high surrogate D83D truncated before its low surrogate. Buffer cutoff at surrogate boundary.

Conceptos clave y arquitectura

Distinciones esenciales para implementar y depurar correctamente cadenas UTF-16 en el software moderno.

Code Unit vs. Code Point vs. Byte

In UTF-16, a code unit is 16 bits (2 bytes). A code point is a numeric index in the Unicode codespace. In the BMP, 1 code point = 1 code unit = 2 bytes. In supplementary planes (e.g. 😀), 1 code point = 2 code units = 4 bytes.

User-Perceived Characters & Grapheme Clusters

A single visible character on screen can require more than one code point. For example, 👩‍💻 (Woman Technologist) consists of 3 code points (Woman U+1F469, ZWJ U+200D, Laptop U+1F4BB) and spans 5 UTF-16 code units (10 serialized bytes). Do not confuse code unit counts with human-perceived characters.

UTF-16 vs. UCS-2

UCS-2 was a legacy fixed-width 16-bit encoding that only supported the Basic Multilingual Plane (U+0000..U+FFFF). UCS-2 had no concept of surrogate pairs and could not represent characters beyond 0xFFFF. UTF-16 superseded UCS-2 by introducing surrogate pairs, enabling representation of all 1,114,112 Unicode code points.

UTF-16 vs. UTF-8

UTF-8 is an 8-bit byte-oriented variable-width encoding (1 to 4 bytes per scalar) that is strictly ASCII-compatible. UTF-16 is a 16-bit code-unit variable-width encoding (2 or 4 bytes per scalar). UTF-8 dominates the web, while UTF-16 is widely used as an in-memory string representation in operating systems and runtimes.

Programming String Length Pitfall (JS, Java, C#)

Many programming language string implementations (such as JavaScript "string".length, Java String.length(), and C# string.Length) count 16-bit UTF-16 code units rather than Unicode code points. Consequently, "😀".length reports 2 instead of 1. Use Array.from(str).length or code-point-aware iterators to count true characters.

Estándares autoritativos y referencias normativas

Todos los datos, los cálculos de sustitutos, las reglas de buena formación y los órdenes de serialización de bytes de esta página derivan directamente de normas técnicas:

  • The Unicode Standard, Version 17.0 — Section 3.8 (Surrogates) & Section 3.9 (Unicode Encoding Forms - Table 3-5) (Unicode Consortium)
  • RFC 2781 — UTF-16, an encoding of ISO 10646 (Internet Engineering Task Force (IETF))
  • WHATWG Encoding Standard — Section 4.5 (utf-16be) & Section 4.6 (utf-16le) (Web Hypertext Application Technology Working Group (WHATWG))