UTF-8 - Définition

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

Introduction

Unicode
Jeux de caractères
  • UCS (ISO/CEI 10646)
  • ISO 646, ASCII
  • ISO 8859-1
  • WGL4
  • UniHan
Équivalences normalisées
  • NFC (précomposée)
  • NFD (décomposée)
  • NFKC (compatibilité)
  • NFKD (compatibilité)
Propriétés et algorithmes
Codage
Autres transformations
  • Punycode
  • GB 18030
Applications d'échanges de données
  • Courriel et Unicode
  • Unicode et HTML

UTF-8 (UCS transformation format 8 bits) est un format de codage de caractères. Il permet de gérer tous les caractères dits unicodes. Chaque caractère est codé sur un ou plusieurs points de code. Chaque point de code est codé sur une suite d’un à quatre octets. Il a été conçu pour être compatible avec certains logiciels originellement prévus pour traiter des caractères d’un seul octet.

Nota Bene: Le concept de point de code (en anglais code point) utilisé dans cet article est un concept défini en anglais pour la norme Unicode, et à la fois en anglais et en français dans la norme ISO/CEI 10646).

D'un point de vue technique, le format de transformation est défini pour tous les points de code ayant une valeur scalaire (qu’ils soient attribués ou non à des caractères ou des « non-caractères ») dans le répertoire universel (Universal Character Set, ou UCS), commun à la norme ISO/CEI 10646 et au standard Unicode (depuis sa version 1.1).

UTF-8 est apparu initialement dans une proposition de standard publiée en 1996 dans la RFC 2044 (« UTF-8, a transformation format of ISO 10646 »). Depuis lors, cette RFC a fait l’objet d’une normalisation par le comité technique de la norme ISO/CEI 10646 qui a publié en 1998 une première révision dans la RFC 2279. À peu près en même temps que le Consortium Unicode et l’ISO ont convenu de synchroniser leurs répertoires, le codage est aussi apparu dans le rapport technique 17 de la norme Unicode. D’autres restrictions ont été ajoutées et incorporées dans le standard Unicode en 2003, où il fait désormais partie intégrante de la norme dans son chapitre 3 « Conformité » (Conformance). À la même date ces restrictions ont été approuvées par l’Organisation internationale de normalisation (ISO) qui a publié la RFC 3629. Le codage UTF-8 est approuvé par l’Internet Engineering Task Force (IETF), qui suit ses évolutions dans le Standard Track BCP 63 ; il est également approuvé par le World Wide Web Consortium (W3C), et la plupart des organismes de normalisation nationaux.

L’IETF requiert maintenant qu’UTF-8 soit pris en charge par tous les nouveaux protocoles de communication d’Internet (publiés dans ses RFC numérotées) qui échangent du texte (les plus anciens protocoles n’ont toutefois pas été modifiés pour rendre ce support obligatoire, mais seulement étendus si possible, pour le supporter de façon optionnelle, si cela produit des incompatibilités ou introduit de nouveaux risques de sécurité : c’est le cas de protocoles Internet très utilisés comme DNS, HTTP, FTP, Telnet et de HTML dans ses versions initiales non normalisées par le W3C).

Description

Le numéro (valeur scalaire) de chaque point de code dans le jeu universel de caractères (UCS) est donné par la norme ISO/CEI 10646 qui assigne un point de code à chaque caractère valide, puis permet leur codage en leur attribuant une valeur scalaire identique au point de code ; cette norme est reprise dans le standard Unicode (qui utilise depuis la version 1.1 le même répertoire).

Tous les « points de code » (code points en anglais) de U+0000 à U+D7FF et de U+E000 à U+10FFFF sont représentables en UTF-8 (mêmes ceux attribués à des « non-caractères » (non character) et tous ceux qui ne sont pas encore attribués), et uniquement ceux-là. Les seuls points de codes valides dans l’espace de l’UCS et qui ne doivent pas être représentés dans UTF-8 sont ceux attribués aux « demi-codets » (surrogates en anglais), car ils ne sont pas représentables de façon bijective dans le codage UTF-16 et ne sont pas non plus par eux-mêmes des caractères : contrairement aux autres points de codes, les demi-codets n’ont donc pas de « valeur scalaire » (scalar value en anglais) définie.

Les caractères dont le point de code attribué (de U+0000 à U+007F) a une valeur scalaire identique de 0 à 127 sont codés sur un seul octet dont le bit de poids fort est toujours nul.

Les points de code de valeur scalaire supérieure à 127 sont codés sur plusieurs octets. Dans ce cas, les bits de poids fort du premier octet forment une suite de 1 de longueur égale au nombre d'octets utilisés pour coder le caractère, les octets suivants ayant 10 comme bits de poids fort.

Définition du nombre d'octets utilisés
Représentation binaire UTF-8 Signification
0xxxxxxx 1 octet codant 1 à 7 bits
110xxxxx 10xxxxxx 2 octets codant 8 à 11 bits
1110xxxx 10xxxxxx 10xxxxxx 3 octets codant 12 à 16 bits
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 4 octets codant 17 à 21 bits

Ce principe pourrait être étendu jusqu’à huit octets pour un seul point de code, mais UTF-8 pose la limite à quatre.

Le codage interdit la représentation des points de code réservés aux demi-codets (qui n’ont pas de valeur scalaire définie, afin de préserver la compatibilité avec UTF-16 qui ne permet pas non plus de les représenter). Mais il autorise cependant la représentation des points de code assignés à des non-caractères (alors même que leur présence est interdite dans un texte conforme).

Exemples

Exemples de codage UTF-8
Type Caractère Point de code
(hexadécimal)
Valeur scalaire Codage UTF-8
décimal binaire binaire hexadécimal
Contrôles U+0000 0 0000000 00000000 00
U+001F 31 0011111 00011111 1F
Texte U+0020 32 0100000 00100000 20
A U+0041 65 1000001 01000001 41
~ U+007E 126 1111110 01111110 7E
Contrôles U+007F 127 1111111 01111111 7F
U+0080 128 00010 000000 11000010 10000000 C2 80
U+009F 159 00010 011111 11000010 10011111 C2 9F
Texte U+00A0 160 00010 100000 11000010 10100000 C2 A0
é U+00E9 233 00011 101001 11000011 10101001 C3 A9
߿ U+07FF 2047 11111 111111 11011111 10111111 DF BF
U+0800 2048 0000 100000 000000 11100000 10100000 10000000 E0 A0 80
U+20AC 8 364 0010 000010 101100 11100010 10000010 10101100 E2 82 AC
U+D7FF 55 295 1101 011111 111111 11101101 10011111 10111111 ED 9F BF
Demi-codets U+D800 (néant) (codage interdit)
U+DFFF
Usage privé U+E000 57 344 1110 000000 000000 11101110 10000000 10000000 EE 80 80
U+F8FF 63 743 1111 100011 111111 11101111 10100011 10111111 EF A3 BF
Texte U+F900 63 744 1111 100100 000000 11101111 10100100 10000000 EF A4 80
U+FDCF 64 975 1111 110111 001111 11101111 10110111 10001111 EF B7 8F
Non-caractères U+FDD0 64 976 1111 110111 010000 11101111 10110111 10010000 EF B7 90
U+FDEF 65 007 1111 110111 101111 11101111 10110111 10101111 EF B7 AF
Texte U+FDF0 65 008 1111 110111 110000 11101111 10110111 10110000 EF B7 B0
U+FFFD 65 533 1111 111111 111101 11101111 10111111 10111101 EF BF BD
Non-caractères U+FFFE 65 534 1111 111111 111110 11101111 10111111 10111110 EF BF BE
U+FFFF 65 535 1111 111111 111111 11101111 10111111 10111111 EF BF BF
 
Texte 𐀀 U+10000 65 536 000 010000 000000 000000 11110000 10010000 10000000 10000000 F0 90 80 80
𝄞 U+1D11E 119 070 000 011101 000100 011110 11110000 10011101 10000100 10011110 F0 9D 84 9E
🿽 U+1FFFD 131 069 000 011111 111111 111101 11110000 10011111 10111111 10111101 F0 9F BF BD
Non-caractères U+1FFFE 131 070 000 011111 111111 111110 11110000 10011111 10111111 10111110 F0 9F BF BE
U+1FFFF 131 071 000 011111 111111 111111 11110000 10011111 10111111 10111111 F0 9F BF BF
 
Texte U+20000 131 072 000 100000 000000 000000 11110000 10100000 10000000 10000000 F0 A0 80 80
U+2FFFD 196 605 000 101111 111111 111101 11110000 10101111 10111111 10111101 F0 AF BF BD
Non-caractères U+2FFFE 196 606 000 101111 111111 111110 11110000 10101111 10111111 10111110 F0 AF BF BE
U+2FFFF 196 607 000 101111 111111 111111 11110000 10101111 10111111 10111111 F0 AF BF BF
 
...autres plans réservés...
 
Spéciaux U+E0000 917 504 011 100000 000000 000000 11110011 10100000 10000000 10000000 F3 A0 80 80
U+EFFFD 983 037 011 101111 111111 111101 11110011 10101111 10111111 10111101 F3 AF BF BD
Non-caractères U+EFFFE 983 038 011 101111 111111 111110 11110011 10101111 10111111 10111110 F3 AF BF BE
U+EFFFF 983 039 011 101111 111111 111111 11110011 10101111 10111111 10111111 F3 AF BF BF
 
Usage privé U+F0000 983 040 011 110000 000000 000000 11110011 10110000 10000000 10000000 F3 B0 80 80
U+FFFFD 1 048 573 011 111111 111111 111101 11110011 10111111 10111111 10111101 F3 BF BF BD
Non-caractères U+FFFFE 1 048 574 011 111111 111111 111110 11110011 10111111 10111111 10111110 F3 BF BF BE
U+FFFFF 1 048 575 011 111111 111111 111111 11110011 10111111 10111111 10111111 F3 BF BF BF
 
Usage privé U+100000 1 048 576 100 000000 000000 000000 11110100 10000000 10000000 10000000 F4 80 80 80
U+10FFFD 1 114 109 100 001111 111111 111101 11110100 10001111 10111111 10111101 F4 8F BF BD
Non-caractères U+10FFFE 1 114 110 100 001111 111111 111110 11110100 10111111 10111111 10111110 F4 8F BF BE
U+10FFFF 1 114 111 100 001111 111111 111111 11110100 10111111 10111111 10111111 F4 8F BF BF

Caractéristiques

Dans toute chaîne de caractères codée en UTF-8, on remarque que :

  • tout octet de bit de poids fort nul désigne un unique « point de code » assigné à un caractère du répertoire de l’US-ASCII et codé sur ce seul octet, d’une valeur scalaire identique à celle du codet utilisé dans le codage US-ASCII ;
  • tout octet de bits de poids fort valant 11 est le premier octet d’une séquence unique représentant un « point de code » (assigné à un caractère ou un non-caractère) et codé sur plusieurs octets ;
  • tout octet de bits de poids fort valant 10 est un des octets suivants d’une séquence unique représentant un « point de code » (assigné à un caractère ou un non-caractère) et codé sur plusieurs octets ;
  • aucun octet ne peut prendre une valeur hexadécimale entre C0 et C1, ni entre F5 et FF (le plus haut point de code valide et assigné à un caractère représentable est U+10FFFD ; c’est un caractère à usage privé alloué dans le 17e plan valide).

Le plus grand point de code valide assignable à un caractère valide non privé est U+EFFFD dans le 15e plan (il n’est pas encore assigné mais peut le devenir dans l’avenir), mais le codage UTF-8 peut être utilisé aussi, de façon conforme aux normes, pour représenter n’importe caractère valide à usage privé (dans une des trois plages U+E000 à U+F8FF, U+F0000 à U+FFFFD, et U+100000 à U+10FFFD).

L’acceptation ou non des non-caractères ou des caractères d’usage privé est laissée aux applications ou protocoles de transport de texte. Cependant les non-caractères ne sont normalement pas acceptés dans des textes strictement conformes au standard Unicode où à la norme ISO/CEI 10646.

Certaines applications imposent des restrictions supplémentaires sur les points de code utilisables (par exemple, les standards HTML et XML interdisent, dans tout document conforme à ces spécifications, la présence de la plupart des caractères de contrôle entre U+0000 et U+001F et entre U+0080 et U+009F, en dehors des contrôles de saut de ligne et de la tabulation U+0009 considérés comme des caractères blancs, et interdisent aussi les non-caractères).

Tout point de code est toujours représenté par exactement la même séquence binaire, quelle que soit sa position relative dans le texte, et ces séquences sont autosynchronisées sur la position indivise des codets significatifs (ici les octets : on peut toujours savoir si un octet débute ou non une séquence binaire effective) ; ce codage autorise donc les algorithmes rapides de recherche de texte, tel que l’algorithme de Boyer-Moore.

Ce n’est pas toujours le cas des codages contextuels (qui utilisent généralement la compression de données, par exemple SCSU défini dans la note technique standard UTS#6 optionnelle complétant le standard Unicode) et qui peuvent nécessiter de lire le texte complètement depuis le début, ni des codages basés sur plus d’une seule variable d’état (ou qui incorporent des codes supplémentaires de redondance) ; au mieux certains de ces codages peuvent demander d’utiliser des algorithmes complexes de resynchronisation, basés souvent sur des heuristiques qui peuvent échouer ou conduire à de fausses interprétations si on ne lit pas le texte depuis le début (par exemple BOCU-1).

Principe et unicité du codage

Dans le tableau ci-dessus on voit que le symbole « € », est le caractère de numéro 8364 qui se code en binaire :

0010 000010 101100

qui sont les parties « non graissées » du codage binaire UTF-8.

log24096 = 12 et log28192 = 13 indiquent qu’avec 12 bits on peut coder les 4 096 premiers entiers (de 0 à 4 095), et qu’avec 13 bits on peut coder les 8192 premiers entiers (de 0 à 8 191).

Il faut donc 14 bits pour coder l’entier représentant le caractère « € ». Soit 2 tranches de 6 bits ; et ensuite en regardant dans le tableau "Définition du nombre d'octets utilisés", on voit que l'on dispose en plus de 4 bits ; ce qui nous fait 16 bits pour placer les 14 bits dont nous avons besoin.

Mais bien sûr si nous avions 3 × 6 + 3 = 21 bits nous pourrions là aussi placer nos 14 bits. Il est dit : « Pour des raisons de sécurité, un programme qui décode des caractères au format UTF-8 ne doit pas accepter les séquences UTF-8 qui sont plus longues que nécessaires pour coder ces caractères. ». (« Il risquerait d'abuser un test de sous-chaîne, qui ne regarderait que les codages les plus courts ».)

Ainsi « € » se codera : 11100010 10000010 10101100,
mais ne se codera pas : 11110000 10000010 10000010 10101100.

Une telle forme, plus longue que nécessaire s'appelle en anglais overlong. De telles formes (initialement autorisées dans des spécifications anciennes avant qu’elles soient normalisées successivement par la RFC initiale publiée par le Consortium X/Open, puis parallèlement par la norme ISO 10646 et le standard Unicode) sont interdites et doivent être traitées comme invalides.

Types d’octets, séquences valides et décodage

Le codage est prédictif et permet toujours de retrouver la position du premier octet d'une séquence représentant un point de code, à partir de la valeur d’un octet quelconque et de la lecture d’un nombre limité d’octets voisins, dans les deux directions de lecture (ce sera toujours l’octet lui-même, ou le premier éligible dans un des 1 à 3 octets voisins).

  • Tout octet de continuation dans une séquence UTF-8 valide ne peut prendre que les valeurs hexadécimales 80 à BF ;
    • il ne peut exister qu’à la suite d’un octet de début de séquence (représentant un point de code), qui sera le dernier codé dans un des 1 à 3 octets précédents et qui n’est pas non plus un octet de continuation ;
    • le point de code suivant, s’il y en a un, ne peut commencer au maximum que dans les 1 à 3 octets suivants.
  • Le premier octet d’une séquence UTF-8 valide ne peut prendre que les valeurs hexadécimales 00 à 7F ou C2 à F4 :
    • le premier octet hexadécimal 00 à 7F d’une séquence n’est suivi d’aucun octet de continuation ;
    • le premier octet hexadécimal C2 à DF d’une séquence est toujours suivi d’un seul octet de continuation (chacun de valeur hexadécimale entre 80 et BF) ;
    • le premier octet hexadécimal E0 à EF d’une séquence est toujours suivi de deux octets de continuation (chacun de valeur hexadécimale entre 80 et BF) ;
      • cependant, si le premier octet d’une séquence prend la valeur hexadécimale ED, le premier octet de continuation est restreint à une valeur hexadécimale entre 80 et 9F ;
    • le premier octet hexadécimal F0 à F4 d’une séquence est toujours suivi de trois octets de continuation (chacun de valeur hexadécimale entre 80 et BF) ;
      • cependant, si le premier octet d’une séquence prend la valeur hexadécimale F4, le premier octet de continuation est restreint à une valeur hexadécimale entre 80 et 8F.

Séquences interdites

  • Les points de code sont toujours représentés par la séquence d’octets la plus courte possible.
    • Par conséquent, aucune séquence d’octets ne contient des octets initiaux de valeur hexadécimale C0 ou C1 dans un texte valide codé en UTF-8.
  • Les points de code allant de U+D800 à U+DFFF sont interdits.
    • Par conséquent, le premier octet de continuation d'une séquence qui commence par l’octet hexadécimal ED ne peut prendre aucune des valeurs hexadécimales A0 à BF.
  • De même que tout codage pouvant donner un point de code de valeur supérieure à U+10FFFF est interdit.
    • Par conséquent, le premier octet de continuation d'une séquence qui commence par l’octet hexadécimal F4 ne peut prendre aucune des valeurs hexadécimales 90 à BF.
    • Et aucune séquence d’octets ne contient des octets initiaux de valeur hexadécimale F5 à FF.

De telles séquences sont dites mal formées (ill-formed). (Voir la référence ci-dessus ou l’article Unicode).

En revanche, les points de code réservés (pas encore alloués à des caractères) sont autorisés (même si l’interprétation des caractères peut rester ambigüe) : il appartient aux applications de décider si ces caractères sont acceptables ou non, sachant que les mêmes applications continueront probablement à être utilisées alors que ces positions auront été assignées dans les normes Unicode et ISO 10646 à de nouveaux caractères parfaitement valides.

De même les autres points de code assignés de façon permanente aux autres « non-caractères » sont interdits dans les textes conformes à la norme ISO/CEI 10646 ou au standard Unicode : par exemple U+xFFFE à U+xFFFF (où x indique un numéro de page hexadécimal de 0 à 10). Mais ils restent encodables et décodables en tant que tels en UTF-8 (les non-caractères sont à disposition des applications qui peuvent en faire un usage au sein d’API internes, par exemple comme codes intermédiaires nécessaires à l’implémentation de certains traitements).

La restriction de l’espace de représentation aux seuls points de code inférieurs ou égaux à U+10FFFF (non compris les points de codes assignés aux demi-codets) n’a pas toujours été appliquée :

  • Cela n’a pas toujours été le cas dans la norme ISO/CEI 10646, qui prévoyait à l’origine de pouvoir coder un très grands nombre de plans possibles (l‘UCS-4 permettait un codage jusqu’à 31 bits), alors que Consortium Unicode (depuis la fusion du répertoire commun dans sa version 1.1) n’utilisait encore que le plan multilingue de base et n’avait pas encore envisagé de couvrir autant d’écritures qu’aujourd’hui.
  • L’introduction par Unicode du codage UTF-16 dans une annexe standard (quand il a admis que plus de 65536 caractères seraient rapidement nécessaires) a demandé l’allocation préalable par l’ISO/IEC 10646 d’un bloc de points de codes pour des « demi-codets » qui étaient considérés au début par l’ISO/IEC 10646 comme des caractères spéciaux (une concession faite à Unicode alors que l’UCS-4 avait été créé comme un espace de codage linéaire où tous les points de code avaient une valeur scalaire), alors qu’Unicode n’utilisait encore que le sous-espace UCS-2 et pas l’espace UCS-4 complet.
    • Pour éviter des problèmes d’interopérabilité avec les autres applications (non Unicode) basées sur UCS-2, une première révision de l’UTF-8 a été publiée par l’ISO en 1998, mentionnant que ces demi-codets n’avaient donc pas de valeur scalaire définie et qu’aucun point de code assignés aux « demi-codets » dans les deux blocs successifs alloués ne devait pas être encodés en UTF-8.
  • Mais selon l’accord final intervenu entre le comité technique du Consortium Unicode et le celui en charge de la norme ISO/CEI 10646, toute utilisation de plus de 17 plans a été proscrite, afin d’assurer l’interopérabilité totale avec le codage UTF-16 défini par Unicode, un codage déjà massivement déployé dans les systèmes d’exploitation (par exemple Microsoft Windows), ou sous-systèmes (par exemple OpenType), ou encore dans de nombreux langages de programmation qui en dépendent pour leur interopérabilité (dont certains issus de normes nationales ou internationales, tels que les langages C et C++ qui ont eu des difficultés à supporter le répertoire universel).
    • En effet, après une vingtaine d’années d’efforts pour la définition de l’UCS pour toutes les écritures du monde, des règles plus strictes ont été établies pour limiter les caractères encodables selon un modèle assurant une compatibilité ascendante mais aussi de meilleures pratiques de codage. Pratiquement toutes les écritures modernes du monde ont été codées, et on dispose d’estimations fiables de l’ordre de grandeur sur la quantité de caractères nécessaires pour le support des autres écritures, ainsi que sur les besoins de codage pour de nouveaux caractères.
    • La croissance initiale très forte des allocations dans l’UCS (ou des caractères restant encore à coder) s’est fortement ralentie, et seulement 5 des 17 plans sont utilisés en fin 2009 (mais deux seulement ont un taux de remplissage significatif : le plan de base multilingue, pratiquement plein, et le plan idéographique supplémentaire ; c’est sur le plan multilingue supplémentaire que se concentrent la majorité des autres écritures anciennes restant à encoder, ou des nouveaux ensembles de symboles et caractères de notation technique).
    • Le rythme de croissance des allocations dans l’UCS pour la norme ISO/IEC 10646 ne permet pas d’envisager sa saturation avant un terme dépassant de très loin le cycle de vie des normes internationales (et encore plus celui des standards industriels comme Unicode). À ce terme trop lointiain, il est tout à fait possible que UTF-16 soit devenu obsolète depuis fort longtemps, ou qu’une nouvelle norme de codification ait vu le jour et ait été massivement déployée (et que les outils de conversion automatique auront aussi été normalisés et déployés). Rien ne justifie encore de maintenir une extension possible non nécessaire au besoin immédiat d'interopérabilité des normes et standards actuels ou des futures normes envisagées.
    • Un ou deux autres plans seulement sont envisagés pour les écritures sinographiques, anciennes écritures cunéiformes ou hiéroglyphiques, et éventuellement un autre plan pour des collections de symboles et pictogrammes nécessaires à l’interopérabilité de certaines applications modernes (par exemple les emojis des messageries et services interactifs est-asiatiques, ou des symboles nécessaires à des normes internationales de signalisation ou de sécurité).
    • Les « groupes » supplémentaires d’usage privé à la fin de l’UCS-4, ainsi que les « plans » supplémentaires d’usage privé dans l’UCS-4 à la fin du groupe 0, qui avaient été envisagés par l’ISO depuis le début de ses travaux de normalisation, ont été abandonnés pour ne garder, parmi les 17 premiers plans du premier groupe, que les deux derniers plans à cet usage privé (en plus du bloc d’usage privé U+E000 à U+F8FF déjà alloué dans le plan multilingue de base), ce qui s’avère suffisant pour toutes les applications.
    • Cela a fait l‘objet de la révision en 2003 de la RFC publiée par le comité technique de l’ISO définissant le codage UTF-8 pour la norme ISO/CEI 10646, et simultanément d’une mise à jour de l’annexe standard au standard Unicode (une annexe standard qui a, depuis, été intégrée au standard lui-même).
    • Depuis ces mises à jour de 2003, le codage UCS-4 défini par la norme ISO/CEI 10646 est devenu en pratique équivalent à UTF-32 (défini dans la norme Unicode qui adjoint des propriétés supplémentaires mais sans différence de codage). Et la dernière RFC publiée par l’ISO et approuvée par l’IETF en 2003 fait d’ailleurs maintenant une référence normative à la définition de l’UTF-8 publiée conjointement avec (ou dans) le standard Unicode.
Page générée en 0.177 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 | Partenaire: HD-Numérique
Version anglaise | Version allemande | Version espagnole | Version portugaise