Chapitre 8.3Unicode et encodage

Comment les machines représentent tous les caractères du monde.

3 minutes de lecture

Comment un ordinateur affiche-t-il la lettre "A" ? Et le caractère chinois "中" ? Et l'emoji "😀" ?

Un ordinateur ne manipule que des nombres, comme l'explique le chapitre Les octets. Pour afficher du texte, il lui faut donc une table de correspondance, où le nombre 65 vaut "A", le nombre 66 vaut "B", et ainsi de suite. Cette table s'appelle un jeu de caractères.

L'histoire de ces tables est celle d'un problème trivial devenu, à force de vouloir contenter tout le monde, franchement compliqué.

ASCII : le début

Au début des années 1960, les Américains normalisent ASCII (American Standard Code for Information Interchange). C'est une table de 128 caractères qui tient sur 7 bits. On y trouve les lettres de A à Z en majuscules et en minuscules, les chiffres de 0 à 9, la ponctuation, l'espace, et une trentaine de caractères de contrôle invisibles comme le retour à la ligne ou la tabulation.

128 cases, ça suffit pour l'anglais. Mais que fait-on du français et de ses accents ? De l'allemand et de ses trémas ? Du japonais et de ses milliers de kanji ?

Comme un octet compte 8 bits, il restait 128 places libres. Chaque région s'y est engouffrée avec sa propre table. Latin-1 pour l'Europe de l'Ouest, une autre pour l'Europe centrale, une autre pour le cyrillique, une autre pour le grec, sans compter les systèmes bien plus tordus inventés en Asie pour loger des milliers d'idéogrammes.

Le résultat était prévisible. Un texte écrit sur un ordinateur français devenait illisible sur un ordinateur russe, parce que le même nombre ne désignait plus le même caractère. C'est ce qu'on appelle le mojibake, ces suites de symboles absurdes qu'on croise encore parfois dans un vieil email ou un fichier exporté à la va-vite.

Exemple :

Tu exportes un fichier client depuis ton outil, tu l'ouvres dans un tableur, et "Café" s'affiche "Café". Rien n'est perdu, le fichier est correct. C'est le tableur qui lit les octets avec la mauvaise table, comme si on lisait un texte allemand en appliquant les règles de prononciation du français.

Unicode : une table universelle

Au début des années 1990, un consortium international se donne pour mission de créer une table unique contenant tous les caractères de toutes les écritures du monde, passées et présentes. C'est Unicode.

Unicode attribue un numéro unique, appelé "point de code", à chaque caractère. On le note avec le préfixe U+ suivi de sa valeur en hexadécimal.

  • U+0041 : A (alphabet latin)
  • U+00E9 : é (latin avec accent aigu)
  • U+4E2D : 中 (chinois, "milieu")
  • U+1F600 : 😀 (visage souriant)

Les 128 premiers points de code reprennent exactement ASCII, dans le même ordre. Ce choix de compatibilité, apparemment anodin, a énormément compté dans l'adoption de la norme.

Unicode contient aujourd'hui plus de 150 000 caractères, couvrant plus de 160 écritures. Latin, arabe, cyrillique, chinois, japonais, coréen, hébreu, thaï, géorgien, tibétain, cunéiforme, hiéroglyphes égyptiens, et bien sûr les emojis, qui font l'objet d'un processus d'ajout annuel très suivi. L'espace total prévu par la norme dépasse le million de positions, il reste donc de la place.

UTF-8 : la représentation dominante

Unicode dit quels caractères existent et quel numéro leur est attribué. Reste à décider comment écrire ces numéros sous forme d'octets dans un fichier ou sur le réseau. C'est le rôle de l'encodage, et le grand gagnant s'appelle UTF-8.

Son astuce est d'utiliser un nombre variable d'octets selon le caractère. Les caractères ASCII tiennent sur 1 octet, exactement comme avant. Les lettres accentuées, le grec et le cyrillique prennent 2 octets. La plupart des idéogrammes asiatiques en prennent 3. Les emojis en prennent 4.

Le compromis est brillant. Un texte en anglais ou un fichier de code source ne prennent pas un octet de plus qu'avant, tout en pouvant contenir n'importe quel caractère du monde dès qu'on en a besoin. Un ancien fichier ASCII est d'ailleurs déjà, sans rien faire, un fichier UTF-8 valide. C'est pourquoi UTF-8 s'est imposé comme le standard de fait, avec autour de 98% des pages web.

Tu croiseras aussi UTF-16, qui code la plupart des caractères sur 2 octets et le reste sur 4, et UTF-32, qui en utilise 4 pour tout le monde. Ils représentent exactement les mêmes caractères Unicode, seule la façon de les écrire en mémoire change. Certains environnements plus anciens les emploient encore en interne.

Pourquoi les développeurs s'en soucient

L'encodage est une source de bugs particulièrement sournoise, parce que tout semble fonctionner jusqu'au jour où un client s'appelle Nguyễn ou Müller.

  • La longueur d'une chaîne : l'emoji famille "👨‍👩‍👧‍👦" est visuellement un seul symbole, mais il est composé de quatre emojis reliés par trois liants invisibles, soit sept points de code. Selon la façon de compter, le même texte aura trois longueurs différentes, ce qui explique bien des compteurs de caractères qui déraillent sur les réseaux sociaux.
  • La comparaison : le caractère "é" peut s'écrire de deux manières, soit comme un point de code unique (U+00E9), soit comme un "e" suivi d'un accent combinant (U+0065 puis U+0301). Les deux sont visuellement identiques et pourtant différents pour la machine. C'est un grand classique du "j'ai bien tapé mon nom et le site me dit qu'il ne me trouve pas". La parade s'appelle la normalisation, une étape qui réécrit le texte sous une forme canonique avant de le comparer.
  • Le tri alphabétique : en français, "é" se range avec "e". En suédois, "ä" est une lettre à part entière qui vient après le z. Le bon ordre dépend de la langue du lecteur et pas du numéro Unicode, sujet que creuse le chapitre Localisation et internationalisation.
  • Les majuscules : passer un texte en majuscules n'est pas une opération neutre. En turc, le i sans point et le i avec point sont deux lettres distinctes, et appliquer les règles anglaises produit un mot faux.
  • La sécurité : certaines lettres cyrilliques ressemblent trait pour trait à leurs équivalents latins. Des attaquants s'en servent pour enregistrer des noms de domaine visuellement identiques à ceux d'une banque. Les navigateurs affichent désormais ces adresses sous une forme technique pour éviter le piège.

Ce qu'il faut retenir

En pratique, la règle est simple. Tout doit être en UTF-8, de bout en bout, la base de données, les fichiers, les pages web, les emails et les exports. Les problèmes d'encodage n'apparaissent presque jamais au sein d'un système bien réglé, ils surgissent aux frontières, quand une donnée passe d'un outil à un autre qui n'a pas fait le même choix.

Si un jour un développeur te dit qu'il a passé son après-midi sur un problème d'accents, ne souris pas trop vite. Il vient de rencontrer quarante ans d'histoire informatique condensés dans un seul caractère.

PrécédentLa programmation objet Tous les chapitres