Qu'est-ce que l'Encodage Unicode ?
Unicode est une norme universelle d'encodage de caractères qui attribue un numéro unique — appelé point de code — à chaque caractère utilisé dans les langues humaines. Avant Unicode, il existait des dizaines de systèmes d'encodage incompatibles. Un document écrit en russe sur un système était illisible sur un autre. Unicode résout ce problème en fournissant un jeu de caractères unique et unifié qui couvre plus de 150 systèmes d'écriture et 140 000 caractères.
Unicode lui-même n'est pas un encodage. C'est un répertoire de caractères. La couche d'encodage — comment les points de code sont stockés sous forme d'octets — est gérée par des formes d'encodage comme UTF-8, UTF-16 et UTF-32. Comprendre la distinction entre un point de code et sa représentation en octets est la clé pour éviter les bugs d'encodage.
Points de Code
Chaque caractère Unicode a un point de code écrit sous la forme U+ suivi d'un nombre hexadécimal. La lettre A est U+0041, le signe euro est U+20AC, et l'emoji 😀 est U+1F600.
Les points de code sont organisés en 17 plans, chacun contenant 65 536 caractères. Le premier plan (Plan 0) est le Plan Multilingue de Base (BMP), qui contient les caractères les plus courants, notamment le latin, le grec, le cyrillique, le CJK (chinois, japonais, coréen) et bien d'autres. Les plans 1 à 16 contiennent des caractères supplémentaires comme les emojis, les écritures historiques et les caractères CJK rares.
| Plan | Plage | Nom |
|---|---|---|
| 0 | U+0000 à U+FFFF | Plan Multilingue de Base (BMP) |
| 1 | U+10000 à U+1FFFF | Plan Multilingue Supplémentaire (SMP) |
| 2 | U+20000 à U+2FFFF | Plan Idéographique Supplémentaire (SIP) |
| 3-13 | U+30000 à U+DFFFF | Non attribué |
| 14 | U+E0000 à U+EFFFF | Plan Supplémentaire à Usage Spécial (SSP) |
| 15-16 | U+F0000 à U+10FFFF | Plans à Usage Privé |
UTF-8, UTF-16, UTF-32
Ces trois formes d'encodage diffèrent dans la manière dont elles transforment les points de code en octets.
UTF-8
UTF-8 est l'encodage dominant sur le web. Il utilise 1 à 4 octets par caractère et est rétrocompatible avec l'ASCII. Les caractères de la plage ASCII (U+0000 à U+007F) utilisent un octet. Les écritures européennes utilisent deux octets. Les caractères CJK et les emojis utilisent trois ou quatre octets.
| Plage de Points de Code | Octet 1 | Octet 2 | Octet 3 | Octet 4 |
|---|---|---|---|---|
| U+0000 - U+007F | 0xxxxxxx | |||
| U+0080 - U+07FF | 110xxxxx | 10xxxxxx | ||
| U+0800 - U+FFFF | 1110xxxx | 10xxxxxx | 10xxxxxx | |
| U+10000 - U+10FFFF | 11110xxx | 10xxxxxx | 10xxxxxx | 10xxxxxx |
Avantages d'UTF-8 :
- Le texte ASCII est un UTF-8 valide (aucune conversion nécessaire)
- Auto-synchronisant : vous pouvez toujours trouver les limites des caractères
- Pas de problème d'ordre des octets (little-endian / big-endian)
- Le plus économe en espace pour le texte en écriture latine
UTF-16
UTF-16 utilise 2 octets (une unité de code) pour les caractères BMP et 4 octets (deux unités de code, appelées paires de substitution) pour les caractères supplémentaires. Windows, Java et JavaScript utilisent UTF-16 en interne.
UTF-16 a des problèmes d'ordre des octets. Un fichier UTF-16 doit spécifier s'il est little-endian (UTF-16LE) ou big-endian (UTF-16BE), généralement en utilisant un BOM (Byte Order Mark) au début.
UTF-32
UTF-32 utilise exactement 4 octets pour chaque point de code. C'est simple mais gaspilleur. Un fichier purement ASCII devient quatre fois plus grand. UTF-32 est rarement utilisé en pratique.
Comparaison
| Caractéristique | UTF-8 | UTF-16 | UTF-32 |
|---|---|---|---|
| Octets par caractère | 1-4 | 2 ou 4 | 4 |
| Compatibilité ASCII | Oui | Non | Non |
| Utilisation web | ~98% | ~2% | <0.01% |
| BOM nécessaire | Non | Oui | Oui |
| Courant dans | Web, Linux, JSON | Windows, Java, JS | Traitement interne |
Bugs d'Encodage
Le bug d'encodage le plus courant consiste à traiter les octets comme des caractères. Lorsque vous prenez une chaîne UTF-8 et l'interprétez comme du Latin-1 (ISO 8859-1), les caractères accentués apparaissent comme des symboles illisibles. Cela se produit lorsque l'encodage n'est pas déclaré ou lorsqu'un outil suppose le mauvais encodage.
Un autre problème courant est de compter les octets au lieu des caractères. En UTF-8, la chaîne « café » fait 4 caractères mais 5 octets car é utilise deux octets. Des fonctions comme strlen de PHP comptent les octets par défaut, tandis que mb_strlen compte les caractères.
Exemples de Programmation
// PHP - toujours utiliser les fonctions mb_* pour UTF-8
$text = 'café ☕';
echo strlen($text); // 8 octets (mauvais compte)
echo mb_strlen($text, 'UTF-8'); // 6 caractères
// Encoder/décoder des points de code Unicode
echo mb_convert_encoding($text, 'UTF-16', 'UTF-8');
# Python 3 - les chaînes sont Unicode par défaut
text = 'café ☕'
print(len(text)) # 6 caractères
bytes_utf8 = text.encode('utf-8')
bytes_utf16 = text.encode('utf-16')
print(bytes_utf8) # b'caf\xc3\xa9 \xe2\x98\x95'
// JavaScript - les chaînes sont en UTF-16 en interne
let text = 'café ☕';
console.log(text.length); // 6 (mais les emojis peuvent compter pour 2)
// Encoder en octets UTF-8
let encoder = new TextEncoder();
let bytes = encoder.encode(text);
console.log(bytes); // Uint8Array(8)
Outil en Ligne
L'outil Encodeur et Décodeur Unicode sur Help2Code convertit le texte en points de code Unicode et entre les représentations UTF-8, UTF-16 et UTF-32. Il est utile pour déboguer les problèmes d'encodage et apprendre comment fonctionne Unicode.
Conclusion
L'encodage Unicode est une connaissance essentielle pour tout développeur travaillant avec du texte international. UTF-8 est la norme pour le web et devrait être votre encodage par défaut. Comprendre la différence entre les points de code et les représentations en octets vous aidera à éviter les bugs d'encodage de texte les plus courants. Utilisez l'outil Encodeur et Décodeur Unicode pour expérimenter avec les encodages et déboguer les problèmes d'encodage.