Aller au contenu principal
Encodage 16 bits à largeur variable Unicode Standard 17.0 §3.8 & §3.9 RFC 2781

Encodage UTF-16

UTF-16 (format de transformation Unicode de 16 bits) est l'encodage de caractères à largeur variable qui représente les valeurs scalaires Unicode à l'aide d'une ou deux unités de code de 16 bits (2 ou 4 octets). Les caractères du plan multilingue de base (U+0000 à U+D7FF et U+E000 à U+FFFF) sont mappés directement sur une seule unité de 16 bits. Les caractères des plans supplémentaires (U+10000 à U+10FFFF) — dont les émojis, les alphanumériques mathématiques et les écritures historiques — sont encodés à l'aide d'une paire ordonnée d'unités de code réservées appelée paire de substitution.

Données techniques rapides

Taille d'unité de code 16-bit Code Units (2 Bytes) Unité fondamentale de la forme d'encodage
Unités par valeur scalaire 1 or 2 Code Units (2 or 4 Bytes) 1 unité pour le BMP ; 2 unités pour les supplémentaires
Plan multilingue de base (BMP) U+0000–U+D7FF & U+E000–U+FFFF Mappage scalaire direct 1:1 (1 unité, 2 octets)
Substituts réservés U+D800–U+DFFF 2,048 unités réservées ; pas des caractères scalaires
Plans supplémentaires (1–16) U+10000–U+10FFFF Encodés en paires de substitution (2 unités, 4 octets)
Boutisme / ordre des octets UTF-16BE / UTF-16LE Sérialisation Big-Endian ou Little-Endian
Marque d'ordre des octets (BOM) Optionnelle (U+FEFF) BE: FE FF | LE: FF FE
Base de normes Unicode 18.0 §3.8, §3.9 Table 3-5 / RFC 2781 Standard du Consortium Unicode & de l'IETF

Espace de code et distribution des plages UTF-16

Le standard Unicode partitionne tout l'espace de $1,114,112$ points de code en plans. UTF-16 gère les points de code avec des unités de 16 bits simples pour les caractères scalaires du BMP et des paires d'unités de 16 bits pour les caractères supplémentaires, conformément au tableau 3-5 du standard Unicode 18.0.

Plan de caractères Plage scalaire Unités de code Longueur en octets Plage d'unités de code (hex) Statut d'encodage
Basic Multilingual Plane (BMP, Lower)
Covers ASCII, Latin, Greek, Cyrillic, Hebrew, Arabic, and most common scripts.
U+0000–U+D7FF 1 Unité 2 Octets 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 Unité 2 Octets 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 Unité 2 Octets 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 Unité 2 Octets 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 Unités 4 Octets D800 DC00 – DBFF DFFF Surrogate Pair Required (High Surrogate + Low Surrogate)

Le mécanisme de la paire de substitution

Comme une seule unité de code de 16 bits peut adresser au plus $65,536$ valeurs, Unicode a réservé $2,048$ unités de code dans le plan multilingue de base (plan 0) spécifiquement pour encoder les $1,048,576$ caractères supplémentaires (plans 1–16).

Anatomie d'une paire de substitution (exemple : 😀 U+1F600) 2 unités de code = 4 octets = 1 caractère Unicode
Substitut haut (de tête)
D83D
Plage : 0xD800–0xDBFF
Encode les 10 bits forts ($0\text{x}03\text{D}$)
+
Substitut bas (de queue)
DE00
Plage : 0xDC00–0xDFFF
Encode les 10 bits faibles ($0\text{x}200$)
=
Caractère Unicode décodé
😀
U+1F600
Grinning Face (1 valeur scalaire)

1. Formule d'encodage (scalaire vers substituts)

Pour tout point de code supplémentaire $C$ où $0\text{x}10000 \le C \le 0\text{x}10\text{FFFF}$ :

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

Soustraire $0\text{x}10000$ produit un nombre de 20 bits ($2^{20} = 1,048,576$). Le découpage en deux moitiés de 10 bits s'insère parfaitement dans les deux fenêtres de substitution de 1,024 unités.

2. Formule de décodage (substituts vers scalaire)

Étant donnés un substitut haut valide $W_1$ et un substitut bas valide $W_2$ :

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

Inverse les décalages de 10 bits et ajoute le décalage $0\text{x}10000$ pour reconstruire la valeur scalaire Unicode exacte de 21 bits.

Inspecteur et validateur UTF-16 interactif

Explorez en direct l'encodage des unités de code UTF-16, basculez entre les sérialisations d'octets Big-Endian et Little-Endian, ou saisissez des unités de code hexadécimales brutes pour valider la conformité des séquences.

Préréglages rapides :
Format d'affichage :
Points de code : 1
Unités de code UTF-16 : 2
Octets sérialisés : 4
Clusters de graphèmes : 1
Unités de code UTF-16 hexadécimales :
D83D DE00
😀 U+1F600
Plan multilingue supplémentaire Paire de substitution requise
Substitut haut : D83D
Substitut bas : DE00
Octets BE : D8 3D DE 00
Octets LE : 3D D8 00 DE

Exemple résolu : encodage de 😀 (U+1F600)

Suivez la dérivation mathématique et de décalage de bits exacte définie par le standard Unicode 18.0 pour convertir la valeur scalaire supplémentaire U+1F600 en sa paire de substitution UTF-16 D83D DE00.

Étape 1
Subtract 0x10000
0x1F600 - 0x10000 = 0x0F600
Subtracting the base 0x10000 reduces the code point to a 20-bit value (0x00000..0xFFFFF).
Étape 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).
Étape 3
Add High Surrogate Base (0xD800)
0xD800 + 0x03D = 0xD83D
The high (leading) surrogate unit is computed by adding the top 10 bits to 0xD800.
Étape 4
Add Low Surrogate Base (0xDC00)
0xDC00 + 0x200 = 0xDE00
The low (trailing) surrogate unit is computed by adding the lower 10 bits to 0xDC00.
Étape 5
Surrogate Pair Result
D83D DE00
Together, the ordered pair <0xD83D, 0xDE00> represents U+1F600 in UTF-16.

Vérification par décodage inverse

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

La formule inverse reconstruit la valeur scalaire d'origine avec une fidélité mathématique de 100 %.

Exemples représentatifs à travers les plans

Caractères Unicode représentatifs, symboles mathématiques, écritures historiques, signes combinants et séquences d'émojis complexes encodés en UTF-16.

A

Latin Capital Letter A

ASCII / Basic Latin
Unités de code UTF-16 : 0041
Octets sérialisés BE : 00 41
Octets sérialisés LE : 41 00
1 Code Unité 2 Octets 1 Point de code

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

é

Latin Small Letter E with Acute

Latin-1 Supplement
Unités de code UTF-16 : 00E9
Octets sérialisés BE : 00 E9
Octets sérialisés LE : E9 00
1 Code Unité 2 Octets 1 Point de code

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

€

Euro Sign

Currency Symbols
Unités de code UTF-16 : 20AC
Octets sérialisés BE : 20 AC
Octets sérialisés LE : AC 20
1 Code Unité 2 Octets 1 Point de code

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

∞

Infinity

Mathematical Operators
Unités de code UTF-16 : 221E
Octets sérialisés BE : 22 1E
Octets sérialisés LE : 1E 22
1 Code Unité 2 Octets 1 Point de code

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

😀

Grinning Face

Emoji / SMP
Unités de code UTF-16 : D83D DE00
Octets sérialisés BE : D8 3D DE 00
Octets sérialisés LE : 3D D8 00 DE
2 Code Unités 4 Octets 1 Point de code

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

𐂃

Linear B Ideogram B105F Mare

Historic Scripts (SMP)
Unités de code UTF-16 : D800 DC83
Octets sérialisés BE : D8 00 DC 83
Octets sérialisés LE : 00 D8 83 DC
2 Code Unités 4 Octets 1 Point de code

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

𪚥

CJK Unified Ideographs Extension B

Rare CJK Ideograph (SIP)
Unités de code UTF-16 : D869 DEA5
Octets sérialisés BE : D8 69 DE A5
Octets sérialisés LE : 69 D8 A5 DE
2 Code Unités 4 Octets 1 Point de code

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

é

Combining E + Acute Accent

Combining Sequence
Unités de code UTF-16 : 0065 0301
Octets sérialisés BE : 00 65 03 01
Octets sérialisés LE : 65 00 01 03
2 Code Unités 4 Octets 2 Points de code

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

👩‍💻

Woman Technologist

ZWJ Emoji Sequence
Unités de code UTF-16 : D83D DC69 200D D83D DCBB
Octets sérialisés BE : D8 3D DC 69 20 0D D8 3D DC BB
Octets sérialisés LE : 3D D8 69 DC 0D 20 3D D8 BB DC
5 Code Unités 10 Octets 3 Points de code

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

Ordre des octets et sérialisation : UTF-16BE contre UTF-16LE

UTF-16 définit une forme d'encodage utilisant des unités de code de 16 bits. Quand ces entiers de 16 bits sont sérialisés en un flux d'octets de 8 bits (pour la transmission réseau ou le stockage), l'ordre des deux octets au sein de chaque unité de code est régi par le schéma d'encodage : Big-Endian ou Little-Endian.

Caractère Point de code Unités de code de 16 bits UTF-16BE (Big-Endian) UTF-16LE (Little-Endian) Comportement de sérialisation
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.

Note importante sur l'échange des substituts

En sérialisant une paire de substitution en mode Little-Endian (UTF-16LE), chaque unité de code de 16 bits est échangée par octets individuellement. L'ordre des deux unités de code reste inchangé : le substitut haut précède toujours le substitut bas. Par exemple, D83D DE00 devient 3D D8 00 DE, et NON 00 DE 3D D8.

Sémantique de la marque d'ordre des octets (BOM)

La marque d'ordre des octets (BOM) est le caractère Unicode U+FEFF (ESPACE SANS CHASSE INSÉCABLE). Placée au début d'un flux UTF-16 sérialisé, son motif d'octets révèle immédiatement si le flux est Big-Endian ou Little-Endian.

Signature UTF-16BE
FE FF

L'octet de poids fort 0xFE précède l'octet de poids faible 0xFF. Signale un ordre des octets Big-Endian.

Signature UTF-16LE
FF FE

L'octet de poids faible 0xFF précède l'octet de poids fort 0xFE. Signale un ordre des octets Little-Endian.

Contexte du flux Statut d'exigence Explication normative
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.

Le mythe de l'exigence universelle

UTF-16 n'exige PAS universellement une BOM. Bien que courante dans les fichiers texte Windows (comme les fichiers .txt du Bloc-notes étiquetés "Unicode"), les protocoles spécifiant charset=utf-16le ou charset=utf-16be n'en exigent explicitement pas. Dans les applications web, le standard d'encodage du WHATWG se base sur UTF-8, mais décode les flux UTF-16 étiquetés selon la BOM explicite ou les définitions MIME.

Bonne formation et séquences de substitution mal formées

Une séquence d'unités de code UTF-16 est bien formée si et seulement si chaque unité substitut apparaît dans une séquence correctement appariée et ordonnée. Tout substitut isolé ou dépareillé viole le standard Unicode 18.0 §3.9 (définition D92).

Invariants de conformité Unicode

  • Règle 1 (scalaires du BMP) : les unités de code de 16 bits simples doivent tomber dans U+0000..U+D7FF ou U+E000..U+FFFF.
  • Règle 2 (substituts hauts) : tout substitut haut (0xD800..0xDBFF) doit être immédiatement suivi d'un substitut bas (0xDC00..0xDFFF).
  • Règle 3 (substituts bas) : tout substitut bas (0xDC00..0xDFFF) doit être immédiatement précédé d'un substitut haut (0xD800..0xDBFF).
  • Règle 4 (non-caractères) : les non-caractères (comme U+FDD0..U+FDEF, U+FFFE, U+FFFF) sont des valeurs scalaires Unicode valides et ne doivent jamais être traités comme des erreurs de substitution.
Unités de code (hex) Classification de l'erreur Décalage de l'erreur Diagnostic de conformité au standard Risque de sécurité et d'analyse
D800 UNPAIRED_HIGH_SURROGATE Position 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 Position 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 Position 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 Position 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 Position 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 Position 1 Valid ASCII A (0041) followed by high surrogate D83D truncated before its low surrogate. Buffer cutoff at surrogate boundary.

Concepts fondamentaux et architecture

Distinctions essentielles pour implémenter et déboguer correctement les chaînes UTF-16 dans les logiciels modernes.

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.

Normes de référence et références normatives

Toutes les données, calculs de substitution, règles de bonne formation et ordres de sérialisation des octets de cette page dérivent directement de normes techniques normatives :

  • 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))