UTF-8 - Définition

Source: Wikipédia sous licence CC-BY-SA 3.0.
La liste des auteurs de cet article est disponible ici.

Histoire

UTF-8 a été inventé par Kenneth Thompson lors d'un dîner avec Rob Pike aux alentours de septembre 1992. Il a été immédiatement utilisé dans le système d'exploitation Plan 9 sur lequel ils travaillaient. Une contrainte à résoudre était de coder les caractères nul et '/' comme en ASCII et qu'aucun octet codant un autre caractère n'ait le même code. Ainsi les systèmes d'exploitation UNIX pouvaient continuer à rechercher ces deux caractères dans une chaîne sans adaptation logicielle.

Restrictions successives

Le codage original était alors appelé FSS-UTF (File-System Safe Unicode Transform Format) et était destiné à remplacer le codage multi-octets UTF-1 initialement proposé par l'ISO 1646. Ce codage initialement permissif, permettait plusieurs représentations binaires pour le même caractère (cela a été interdit dans la version normalisée dans la RFC publiée par le Consortium X/Open, et approuvé par Kenneth Thompson).

De plus il pouvait (dans une version préliminaire non retenue) coder tous les caractères dont la valeur de point de code comprenait jusqu'à 32 bits en définissant un huitième type d'octet (dans des séquences comprenant jusqu'à 6 octets), au lieu des 7 types d’octets finalement retenus pour ne coder (dans des séquences comprenant aussi jusqu'à 6 octets) que les points de code jusqu'à 31 bits dans la version initiale d'UTF-8 (publiée par le Consortium X/Open sous le nom FSS-UTF, puis proposé par le comité technique d’ISO 10646 comme la proposition « UTF-2 » alors encore en concurrence avec la proposition « UTF-1 », jusqu'à ce que la proposition UTF-2 soit retenue et adopte le nom UTF-8 déjà retenu et utilisé dans X/Open et Plan 9).

Ce codage UTF-8 a été restreint encore lorsque Unicode et ISO 10636 ont convenu de n'allouer des caractères que dans les 17 premiers plans afin de maintenir indéfiniment la compatibilité avec UTF-16 (sans devoir le modifier), en restreignant les séquences jusqu'à 4 octets seulement et en n’utilisant que les 5 premiers des 7 types d'octets (ce qui a nécessité de définir comme invalides de nouvelles valeurs d’octet et certaines séquences d'octets pourtant valides individuellement).

Prise en charge

  • Navigateurs web : la prise en charge d'UTF-8 commença à être répandue à partir de 1998.
  • Fichiers et noms de fichiers : de plus en plus courant sous les systèmes GNU/Linux, pas très bien supporté sous Windows.
  • Client de messagerie
    • Thunderbird supporte UTF-8
    • Si.Mail supporte UTF-8
    • Lotus Notes supporte UTF-8

Extensions non standards

Toutefois, des variantes d’UTF-8 (basées sur les possibilités de codage de la version initiale non restreinte) ont continué à être utilisées (notamment dans l’implémentation de la sérialisation des chaînes Java) pour permettre de coder sous forme d'un échappement multioctets certains caractères ASCII réservés normalement codés sur un seul octet (par exemple le caractère nul).

De plus, certains systèmes utilisent des chaînes de caractères non restreints : par exemple, Java (et d’autres langages y compris des bibilothèques de manipulation de chaînes en C, PHP, Perl, etc...) représentent les caractères avec des unités de codage sur 16 bits (ce qui permet de stocker les chaînes en utilisant le codage UTF-16, mais sans les contraintes de validité imposées par UTF-16 concernant les valeurs interdites et l'appariement dans l’ordre des « demi-points de code » ou surrogates) ; dans ce cas, les unités de codage sont traitées comme des valeurs binaires et il est nécessaire de les sérialiser de façon individuelle (indépendamment de leur interprétation possible comme caractères ou comme demi-points de code). Dans ce cas, chaque unité de codage 16 bits qui représente un « caractère » (non-contraint) est sérialisé sous forme de séquences comprenant jusqu'à 3 octets chacune, et certains octets interdits par l’implémentation (par exemple les caractères nuls ou la barre de fraction « / » dans un système de fichiers ou d’autres caractères codés sur un octet dans d’autres protocoles) sont codés sous forme de séquences d’échappement à deux octets dont aucun n’est nul, en utilisant simplement le principe de codage de la première spécification de FSS-UTF (avant celle qui a été retenue par le Consortium X/Open dans sa RFC initiale où ces échappements étaient spécifiquement interdits et le sont restés).

Avant l’adoption de la proposition UTF-2 retenue pour UTF-8, il a également existé une variante UTF-1, où les codages multiples étaient impossibles, mais nécessitait un codage/décodage plus difficile devant prendre en compte la position de chaque octet et utilisant un certain nombre de valeurs « magiques ».

Ces variantes ne doivent pas être appelées « UTF-8 ».

Une de ces variantes non standards a fait cependant l’objet d’une standardisation ultérieure (en tant qu’alternative à UTF-16 et utilisant des paires de demi-codets codés chacun sur 3 octets) : voir CESU-8.

Exemple de variante utilisée en Java

Par exemple les API d’intégration des machines virtuelles Java (pour JNI, Java Native Interface ou pour la sérialisation des classes précompilées), qui permettent d’échanger les chaînes Java non contraintes sous forme de séquences d’octets (afin de les manipuler, utiliser ou produire par du code natif, ou pour le stockage sous forme de fichier natif codés en suites d’octets) sont suffixées par "UTFChars" ou "UTF", mais ce codage propre à Java n’est pas UTF-8 (La documentation de Sun la désigne comme modified UTF, mais certains documents plus anciens relatifs à JNI désignent encore ce codage incorrectement sous le nom UTF-8, ce qui a produit des anomalies de comportement de certaines bibliothèques natives JNI, notamment avec les API systèmes d’anciennes plateformes natives qui ne supportent pas nativement les codages de caractères sur plus de 8 bits), car :

  • le caractère nul, présent en tant que tel dans une chaîne Java, est codé sous forme de deux octets non nuls (et non un seul octet nul utilisé pour indiquer la fin de séquence).
  • les surrogates (U+D000 à U+D7FFF) peuvent être codés librement, dans un ordre quelconque, de même que les points de code interdits normalement pour le codage de caractère (par exemple U+FFFF ou U+FFFE) : aucun test de validité n'est demandé
  • les séquences d’octets plus longues (sur 4 octets pour représenter les caractères hors du plan multilangue de base) normalisées et valides dans UTF-8 ne sont pas reconnues par la machine virtuelle dans ses API basées sur modified UTF (ce qui déclenche des exceptions lors de la conversion demandée par le code natif de la chaîne 8 bits vers une chaîne Java gérée par la machine virtuelle) : il faut alors réencoder les caractères hors du plan de base (codés sur 4 octets en UTF-8) sous la forme de deux séquences de 3 octets en modified UTF, une pour chaque surrogate.
  • les chaînes Java (de la classe système String) et le type numéral char sont utilisés aussi pour le stockage (sous forme compacte, non modifiable et partageable) de données binaires quelconques (pas seulement du texte), et peuvent aussi être manipulées dans d’autres codages que l’UTF-16 (la seule contrainte étant que les unités de codage individuelle ne doivent pas dépasser 16 bits et doivent être de valeur positive, le bit de poids fort n'étant pas évalué comme un bit de signe).

En conséquence,

  • les applications écrites en pur Java (sans code natif) et qui nécessitent l’implémentation de contraintes de codage pour être conformes à Unicode pour le texte doivent le demander explicitement et utiliser un des filtres de codage fournis (pour UTF-8, comme aussi pour UTF-16), ou construire et utiliser des classes basées sur la classe String et le type numéral char.
  • un texte UTF-8 valide (et manipulé en code natif dans des chaînes sans caractères nuls) nécessite un prétraitement avant de pouvoir être transmis à la machine virtuelle Java via JNI ; notamment, toute séquence codée sur 4 octets (pour un caractère hors du plan de base) doit être transcodée en deux séquences de 3 octets.
  • les chaînes obtenues depuis une machine virtuelle Java via les interfaces UTF de JNI nécessitent un prétraitement de contrôle de validité ou de filtrage dans le code natif, avant de pouvoir être utilisées comme du texte UTF-8 valide (il faut détecter les occurrences du caractère null codé en deux octets et, si ce caractère est acceptable par le code natif, le transcoder en un seul octet ; il faut vérifier dans le code natif l’appariement correct des surrogates, codés chacun sur 3 octets, et les filtrer si ces séquences ne sont pas refusées comme invalides, puis transcoder toute paire valide de surrogates en une seule séquence de 4 octets seulement et non deux séquences de 3 octets).
Page générée en 0.123 seconde(s) - site hébergé chez Contabo
Ce site fait l'objet d'une déclaration à la CNIL sous le numéro de dossier 1037632
A propos - Informations légales
Version anglaise | Version allemande | Version espagnole | Version portugaise