Steve Frécinaux

Jeux de caractères : c’est quoi ?

Mis à jour le jeudi 1 juillet 2004
Publié sur OpenWeb le dimanche 1 août 2004

La notion de jeu de caractères (charset en anglais) est une notion primordiale pour tout développeur web, et même, de façon plus générale, pour tout programmeur soucieux de préserver une certaine interopérabilité. Pourtant, mon expérience personnelle me force à constater que cette notion reste fort abstraite dans l’esprit de beaucoup de ces développeurs, qui bien souvent ne la connaissent que par l’intermédiaire de la ligne <meta http-equiv="Content- type" content="text/html; charset=iso-8859-1" />, et qui s’imaginent dès lors que la simple modification de cette ligne permet de changer de jeu de caractère. Il n’en est rien. Je vais donc tenter d’éclaircir ici certains points.

Les jeux de caractères que l’on rencontre le plus souvent de notre côté de l’internet sont l’ISO-8859-1, l’UTF-8 et, par la force des choses, le Windows-1252, jeu qui pose quelques problèmes dont je parlerai plus loin.

Une histoire de bits

Vous savez tous qu’un ordinateur est une machine fonctionnant grâce à des calculs binaires (1 ou 0), pour la simple mais bonne raison qu’il est bien plus facile de représenter un nombre en base binaire (qui ne recquiert que deux états, en l’occurence “courant” ou “pas courant”) qu’en base 10 (qui nécessiterait de distinguer dix états physiques). Par voie de conséquence, les fichiers sont eux aussi stockés sous la forme d’une suite de bits, chaque bit ayant la valeur 0 ou 1. Ce sont ces bits que vous voyez lorsque vous éditez un fichier à l’aide d’un éditeur hexadécimal, car chaque valeur hexadécimale (base 16) correspond à 4 bits (16 = 24).

Dans ce cadre, le jeu de caractère représente la façon de représenter chaque caractère (et donc un texte) dans cette base binaire. La plupart des jeu de caractères étant codés sur un octet, soit huit bits, chaque caractère de votre fichier texte correspondrait à une paire de chiffres dans un éditeur hexadécimal. On comprend alors que cette notion est tout ce qu’il y a de plus concret. En effet, tout comme ouvrir un fichier généré par un programme dans un autre programme peut poser quelques difficultés pour des raisons d’encodage de l’information, tenter de visionner un fichier texte (ou une page HTML, qui n’est jamais qu’un fichier texte amélioré) utilisant un certain jeu de caractère à l’aide d’un éditeur ou d’un navigateur gérant un autre jeu de caractère peut amener des résultats étranges, comme une substitution d’un caractère par un autre, ou peut-être un message d’erreur, si aucun caractère du jeu utilisé par le programme ne correspond à la paire hexadécimale renseignée dans le fichier.

Maintenant que vous savez ce qu’est un jeu de caractère, détaillons-en quelques-uns…

Un petit bout d’histoire

Le premier de tous fut l’US-ASCII. Il était codé sur huit bits. Mais dans ces huits bits, seuls sept représentaient une information, le huitième étant un dispositif de sécurité, ce qu’on appelle un bit de parité, pour pallier à la relativement faible fiabilité du matériel mis en oeuvre. Ce bit de parité permettait de détecter une éventuelle erreur qui serait survenue lors de la transmission de l’octet. On disposait donc de 7 bits pour coder le caractère, ce qui donnait un total de 27 combinaisons possibles, et donc de 128 caractères représentables. (Note: il fut décidé que le bit de parité, dont l’étude sort du cadre de cet article, soit en fait positionné en première position parmi les 8 bits utilisés pour représenter le caractère.)

L’ASCII était peut-être suffisant pour échanger de sommaires informations en anglais, mais ne l’était pas pour représenter les autres langues du monde occidental. On décida donc d’« étendre » ce jeu de caractère en utilisant le premier bit de l’octet pour coder lui-aussi une information, laissant ainsi tomber le bit de parité. On obtient donc un jeu étendu de 8 bits utiles, soit 256 caractères représentables, dont les 128 premiers sont communs à tous les jeux étendus, car issus de l’ancêtre commun (ASCII). De nombreux jeux étendus ont vu le jour, pour coder des langues comme le grec ou le russe (alphabet cyrillique), mais aussi pour coder les langues d’Europe occidentale, en intégrant accents et signes ponctuations qui nous sont propres. L’ISO-8859-1, ou ISO-Latin1 était né.

D’autres jeux très répandus sont des variantes de l’ISO-8859-1, comme par exemple le récent ISO-8859-15 (qui est un ISO-8859-1 modifié pour pouvoir contenir des symboles comme le sigle €, trop récent pour être inclus dans la norme originale, ou œ, d’abord oublié pour je-ne-sais quelle raison obscure), ou les jeux propriétaires MacRoman (pour MacOs) et Windows-1252, pour Windows. C’est ce dernier plus particulièrement qui pose quelques problèmes, car de nombreuses pages renseignées comme ISO-8859-1 sont en fait encodées en Windows-1252, ce qui a poussé les navigateurs, du moins sous Windows, à systématiquement représenter les pages renseignée comme utilisant l’ISO-8859-1 (sans distinction) à l’aide du jeu de caractères Windows-1252.

La variété des jeux étendus est comme une preuve éclatante de leur insuffisance. En effet, 256 caractères, ce n’est pas beaucoup, et ça rend surtout impossible la rédaction d’un document en plusieurs langues. Oubliez tout de suite le document texte reprenant des mots japonnais et leur traduction en français. Ont donc vu le jour des jeux de caractères codés sur deux octets, comme l’UCS-2, ce qui porte le nombre de caractères représentables à 216, soit 65 536, ce qui est somme toute confortable. Il existe aussi des jeux de caractères codés sur 32 bits, comme l’UCS-4 (plus de 4 milliards de caractères représentables).

Cependant, on perd alors une caractéristique intéressante des jeux étendus : leur compatibilité en ce qui concerne les 128 premiers caractères, communs, ce qui permet de les utiliser indifféremment pour encoder une page HTML ou même un code source, par exemple en PHP, sans devoir multiplier les fonctions d’interprétation. En effet, les langages de programmation n’utilisent bien souvent que les caractères issus de la norme ASCII. Dans le même ordre d’idées, il devient difficile, voire impossible dans le cas de processus automatiques) de déchiffrer un fichier texte UCS-2 dans un éditeur qui n’est pas prévu pour lui. Nous voici donc confronté à un problème plus sérieux : comment créer un jeu de caractères offrant la possibilité de représenter de nombreux caractères, sans pour autant perdre la compatibilité avec l’ASCII ?

La solution fut d’utiliser un nombre d’octets variable pour représenter les caractères. Ce jeu-miracle s’appelle l’UTF-8. On utilise ainsi entre 1 et 6 octets pour représenter un caractère, en introduisant une convention pour différencier les octets isolés, représentant à eux seuls un caractère, ou les octets groupés, devant être considérés à plusieurs pour pouvoir en extraire l’information. Pour conserver la compatibilité avec l’ASCII et les jeux étendus, il a été décidé que les octets isolés commenceraient par un 0. Cette norme permet de représenter un nombre impressionnant de caractères différents, sans compter le fait qu’elle permet un autre système de représentation, l’agrégation de glyphes, que je ne détaillerai pas ici. Seuls un peu plus de 90 000 caractères ont été attribués pour l’instant.

Une chose importante à savoir à propos de l’UTF-8, c’est qu’il existe en deux variantes : avec ou sans BOM. La BOM est en quelque sorte une signature, présente en tout début de fichier, et permettant de reconnaître un fichier encodé avec UTF-8, et de connaitre l’ordre (big endian ou little endian) dans lequel seront présentés les octets des différents caractères (ce mécanisme existe aussi pour d’autres jeux de caractères multi-octets). Elle est rare car non requise, et, comme dans notre cas particulier, elle présente une information redondante avec les en-têtes fournis par le serveur et l’en-tête XML, elle est inutile et sera donc omise pour éviter tout problème avec des programmes ne la reconnaissant pas.

Les outils

Vous comprenez maintenant qu’il ne suffit pas de décider d’utiliser un jeu de caractères pour l’utiliser de façon effective. Encore faut-il que votre programme d’édition le gère. Voici quelques logiciels, libres, que vous pouvez utiliser pour encoder vos pages en UTF-8 ou en ISO-8859-1 (voyez dans leurs options et dans leurs fichiers d’aide respectifs pour plus de détails) :

  • Unired : petit éditeur, sous Windows uniquement. Gère la coloration syntaxique pour de nombreux formats de documents, et gère une cinquantaine de jeux de caractères différents.
  • Jext : éditeur écrit en Java, et donc accessible sur toutes les plateformes. Il gère la coloration syntaxique pour de nombreux formats de documents, et gère l’UTF-8 et ISO-8859-1, mais de façon bien moins souple qu’Unired.
  • SciTE : éditeur très léger, sous Windows et Linux, qui gère la coloration syntaxique, l’UTF-8 et l’ISO-8859-1, de façon très souple. L’un de mes préférés. Attention, dans le cas de SciTE, l’enregistrement sans BOM se fera en sélectionnant le jeu « UTF-8 Cookie ».
  • Vim et Emacs, sans doute les plus célèbres éditeurs de texte de l’univers du logiciel libre.
  • JEdit, BBEdit, etc.

Voilà, une courte rétrospective vite-faite des jeux de caractères. J’espère que ce survol aura pu désembrumer quelques points importants. Si le sujet vous intéresse, faites-le savoir via les commentaires, et j’approfondirai peut-être le sujet dans un billet ultérieur ;)

Compléments d’information :