Aller au contenu principal

RFC 3629 - UTF-8, un format de transformation d'ISO 10646

Date de publication : Novembre 2003
Statut : Norme Internet (STD 63)
Auteur : F. Yergeau (Alis Technologies)
Remplace : RFC 2279
Catégorie : Standards Track


Résumé (Abstract)

ISO/IEC 10646-1 définit un grand ensemble de caractères appelé Universal Character Set (UCS) qui englobe la plupart des systèmes d'écriture du monde. Cependant, les codages initialement proposés pour l'UCS n'étaient pas compatibles avec de nombreuses applications et protocoles actuels, ce qui a conduit au développement d'UTF-8, l'objet de ce mémo. UTF-8 a la caractéristique de préserver la plage complète US-ASCII, offrant une compatibilité avec les systèmes de fichiers, les analyseurs et autres logiciels qui dépendent des valeurs US-ASCII mais sont transparents aux autres valeurs. Ce mémo remplace et rend obsolète la RFC 2279.


Statut de ce mémo (Status of this Memo)

Ce document spécifie un protocole de la piste des normes Internet pour la communauté Internet et demande des discussions et des suggestions d'améliorations. Veuillez vous référer à l'édition actuelle de « Internet Official Protocol Standards » (STD 1) pour connaître l'état de standardisation et le statut de ce protocole. La distribution de ce mémo est illimitée.


Copyright (C) The Internet Society (2003). Tous droits réservés.


Table des matières (Table of Contents)

Sections principales


Pourquoi UTF-8 est-il important ?

UTF-8 est le codage de caractères standard pour l'Internet moderne. Presque toutes les applications web modernes, les API et les formats de données utilisent UTF-8.

Avantages principaux

CaractéristiqueDescriptionImportance
Compatible ASCIILes caractères ASCII sont codés de manière identique⭐⭐⭐⭐⭐
Pas de problème d'ordre des octetsPas de problème d'endianness⭐⭐⭐⭐⭐
Auto-synchronisantPeut décoder depuis n'importe quelle position⭐⭐⭐⭐
Efficace en espace1 octet pour l'anglais, 3 octets pour le CJC⭐⭐⭐⭐
Support universelSupporte tous les caractères Unicode⭐⭐⭐⭐⭐

Référence rapide des règles de codage UTF-8

Tableau de codage

Plage Unicode              Octets  Modèle d'octets UTF-8
─────────────────────────────────────────────
U+0000 - U+007F 1 0xxxxxxx
U+0080 - U+07FF 2 110xxxxx 10xxxxxx
U+0800 - U+FFFF 3 1110xxxx 10xxxxxx 10xxxxxx
U+10000 - U+10FFFF 4 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

Couverture des plages de caractères

1 octet (ASCII) :
- Lettres latines, chiffres, ponctuation de base
- Caractères de contrôle
- Plage : U+0000 - U+007F

2 octets :
- Extensions latines
- Grec, cyrillique, arabe, hébreu
- Plage : U+0080 - U+07FF

3 octets :
- Caractères CJC (chinois, japonais, coréen)
- La plupart des autres systèmes d'écriture
- Plage : U+0800 - U+FFFF

4 octets :
- Émojis
- Écritures historiques, caractères CJC rares
- Plage : U+10000 - U+10FFFF

Exemples de codage

Caractère ASCII

Caractère : 'A'
Unicode : U+0041
Binaire : 0100 0001
UTF-8 : 0x41
Octets : 1

Processus de codage :
U+0041 < U+007F → utiliser le modèle à 1 octet
0xxxxxxx → 01000001 → 0x41

Caractère chinois

Caractère : '你'
Unicode : U+4F60
Binaire : 0100 1111 0110 0000
UTF-8 : 0xE4 0xBD 0xA0
Octets : 3

Processus de codage :
U+4F60 dans la plage U+0800-U+FFFF → utiliser le modèle à 3 octets
1110xxxx 10xxxxxx 10xxxxxx
↓ ↓ ↓
0100 111101 100000
↓ ↓ ↓
11100100 10111101 10100000
0xE4 0xBD 0xA0

Émoji

Caractère : '😀'
Unicode : U+1F600
Binaire : 0001 1111 0110 0000 0000 0000
UTF-8 : 0xF0 0x9F 0x98 0x80
Octets : 4

Processus de codage :
U+1F600 dans la plage U+10000-U+10FFFF → utiliser le modèle à 4 octets
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
↓ ↓ ↓ ↓
000011 111101 100000 000000
↓ ↓ ↓ ↓
11110000 10011111 10011000 10000000
0xF0 0x9F 0x98 0x80

Caractéristiques uniques d'UTF-8

1. Compatibilité ASCII

Fichier ASCII = Fichier UTF-8 valide

Exemple :
Hello World (ASCII)
est également un UTF-8 valide

Raison :
ASCII utilise 7 bits (0xxxxxxx)
La forme à 1 octet d'UTF-8 est ASCII

2. Auto-synchronisation

Flux d'octets UTF-8 :
... E4 BD A0 E5 A5 BD ...
你 好

À partir de n'importe quelle position :
- L'octet initial (1110xxxx ou 110xxxxx ou 11110xxx) marque le début du caractère
- Les octets de continuation (10xxxxxx) ne sont jamais confondus avec l'octet initial

Exemple :
E4 BD A0 E5 A5 BD
↑ ↑
En commençant ici, on identifie ceci comme un octet de continuation
En commençant ici, on identifie un nouveau caractère

3. Pas de problème d'ordre des octets

UTF-16 nécessite un BOM :
FE FF ... (Big Endian)
FF FE ... (Little Endian)

UTF-8 n'en a pas besoin :
L'ordre des octets est fixe, du plus significatif au moins significatif
Pas besoin de BOM pour indiquer l'ordre des octets

Applications courantes

Développement Web

<!-- Fichier HTML -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Exemple UTF-8</title>
</head>
<body>
<p>你好,世界! Hello, World! 😀</p>
</body>
</html>

Protocole HTTP

HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Content-Length: 1234

<!DOCTYPE html>...

Données JSON

{
"name": "张三",
"message": "Hello 世界",
"emoji": "😀"
}

Base de données

CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Points clés des considérations de sécurité

⚠️ Attaque par forme non minimale

Codages trop longs interdits :

Correct : 'A' → 0x41 (1 octet)
Incorrect : 'A' → 0xC0 0x81 (2 octets, trop long)
'A' → 0xE0 0x80 0x81 (3 octets, trop long)

Danger :
Les codages trop longs peuvent contourner les vérifications de sécurité
Exemple : traversée de chemin "../" en codage trop long

⚠️ Séquences invalides

Doit rejeter :
- Octets de continuation isolés (10xxxxxx)
- Au-delà de la plage Unicode (>U+10FFFF)
- Paires de substitution UTF-16 (U+D800-U+DFFF)
- Séquences multi-octets tronquées

Support des langages de programmation

Python

# Codage
s = "你好世界"
b = s.encode('utf-8') # objet bytes

# Décodage
s = b.decode('utf-8') # objet str

# Opérations sur fichiers
with open('file.txt', 'r', encoding='utf-8') as f:
content = f.read()

JavaScript

// Codage
const str = "你好世界";
const encoder = new TextEncoder();
const bytes = encoder.encode(str); // Uint8Array

// Décodage
const decoder = new TextDecoder('utf-8');
const text = decoder.decode(bytes); // string

Java

// Codage
String str = "你好世界";
byte[] bytes = str.getBytes(StandardCharsets.UTF_8);

// Décodage
String decoded = new String(bytes, StandardCharsets.UTF_8);

// Opérations sur fichiers
Files.readString(path, StandardCharsets.UTF_8);

Go

// La chaîne Go est nativement UTF-8
s := "你好世界"

// Convertir en slice d'octets
b := []byte(s)

// Convertir depuis une slice d'octets
s = string(b)

Caractéristiques de performance

Comparaison de l'efficacité spatiale

Type de texteUTF-8UTF-16UTF-32
Anglais1 octet2 octets4 octets
Chinois3 octets2 octets4 octets
Émoji4 octets4 octets4 octets
Texte à dominante anglaise : UTF-8 optimal
Texte à dominante CJC : UTF-16 légèrement meilleur
Texte mixte : UTF-8 généralement optimal


Outils de diagnostic rapide

Identifier le codage UTF-8

def is_utf8(data):
"""Détecter si les données sont UTF-8 valides"""
try:
data.decode('utf-8')
return True
except UnicodeDecodeError:
return False

Corriger les problèmes de codage

# Problème courant : double codage
# Original : "你好"
# Affichage incorrect : "ä½ å¥½"

# Méthode de correction :
text = "ä½ å¥½"
fixed = text.encode('latin1').decode('utf-8')
# Résultat : "你好"

Note importante : UTF-8 est la norme par défaut pour l'Internet moderne. Utilisez toujours le codage UTF-8 et évitez les codages hérités tels que GBK, ISO-8859-1, Windows-1252, etc. Tous les nouveaux projets devraient utiliser UTF-8 comme seul codage de caractères.