Unicode |
---|
Jeux de caractères
|
Équivalences normalisées
|
Propriétés et algorithmes |
Codage
|
Autres transformations
|
Applications d'échanges de données
|
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).
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.
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).
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 |
Dans toute chaîne de caractères codée en UTF-8, on remarque que :
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).
Dans le tableau ci-dessus on voit que le symbole « € », est le caractère de numéro 8364 qui se code en binaire :
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 ».)
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.
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).
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 :