UTF-8 et Unicode

UNICODE et son codage UTF-8 permettent l’utilisation de tous les caractères (accentués ou non, pictogrammes, idéogramme ou émoticones) dans les chaînes et s’imposent de ce fait de plus en plus sur les pages Internet et dans les langages de programmation. Ces caractères n’apparaissent bien sûr que dans la mesure où ils sont pris en compte dans une police chargée sur votre système.

UTF-8 et Unicode sont souvent confondus, mais il s’agit de deux choses distinctes :

L’encodage est donc variable et dépend de la valeur du point de code :

Équivalences hexadécimal / binaire

0 = 0000
1 = 0001
2 = 0010
3 = 0011
4 = 0100
5 = 0101
6 = 0110
7 = 0111
8 = 1000
9 = 1001
A = 1010
B = 1011
C = 1100
D = 1101
E = 1110
F = 1111

Notes :

Encodages UTF-8

Avec la convention des lettres a à u pouvant valoir 0 ou 1, voici les quatre formes d’encodage :

1. 0abcdefg

Tout octet dont le bit le plus fort est nul (donc inférieur à 128) code nécessairement un caractère ASCII. Les sept lettres valant 0 ou 1 : 27 =128 caractères, bien que la plupart des octets inférieurs à 32 ne soient pas utilisés dans les simples textes, qu’il s’agisse de page HTML ou des chaînes de caractères dans la plupart des langages de programmation.

Les caractères ASCII, dont les points de code sont inférieurs à 128, sont repris tels quels dans le codage UTF-8.

2. 110abcde 10fghijk

Si le point de code dépasse 127, le caractère doit être codé sur au moins deux octets. Sous forme binaire,

Cette formule peut théoriquement coder 211 =2 048 caractères sauf les 128 premiers, déjà codés sur un seul octet.

Le premier octet ne peut valoir 0xC0 ni 0xC1, car deux octets de la forme 11000000 10abcdef coderaient les caractère ASCII de 0 à 63 et 11000001 10abcdef ceux de 64 à 127).

Le second octet commence immanquablement par le bit de poids fort de 1 et le second de 0, soit les valeurs entre 128 et 191. Tout autre octet ne peut servir à coder un point de code valable. De ce fait, un texte sauvegardé en latin1 ou cp1252 n’est pas entièrement lu dans un environnement UTF-8, et chaque octet non compatible UTF-8 est souvent affiché . Cette remarque vaut pour les points suivants.

Les points de codes 128-2047, convertis en deux octets, servent à coder les caractères latins accentués, l’alphabet de prononciation international, et de très nombreux alphabets.

3. 1110abcd 10efghij 10klmnop

À partir du point de code 2048, trois octets sont nécessaires, dont le premier qui commence nécessairement par 1110, soit le quartet 14 (en hexadécimal 0xE). Les deux octets qui suivent commencent également par 10. La couverture théorique de points de code est de 216 =65.536 caractères. Les 2048 premiers points de code ne sont bien entendu pas concernés par la transformation en trois octets.

Les points de codes 2048-65535 convertis en trois octets sert à coder quelques alphabet plus rares ou en quelques compléments (le grec polytonique), de nombreux symboles mathématiques, à la ponctuation typographique, aux caractères semi-graphiques, aux dingbats et aux idéogrammes orientaux.

4. 11110abc 10defghi 10jklmno 10pqrstu

le codage UTF8 utilise quatre octets pour les caractères dont le point de code dépasse 65 535. Le premier commence nécessairement par un quartet égal à 15 (0xF en hexadécimal), le deuxième quartet étant inférieur à 8. Les trois octets suivants commencent tous par 10. Le nombre théorique de caractères codés sur quatre octets est de 221 =2 097 152.

Les caractères codés en quatre octets concernent en général des écritures anciennes (le cunéiforme, les hiéroglyphes) ou les émoticones en couleurs. Certains serveurs SQL ne les gèrent pas.

Et ensuite ?

Il ne serait pas impossible de coder sur cinq octets (26 bits codables, 67 108 864 caractères), voire six (31, 2 147 483 648), mais la norme prévoit quatre octets maximum.

Discussion

Le format UTF-8 est pratique pour les programmeurs : si un caractère est codé avec une suite de quatre octets WXYZ, aucun autre caractère n’est codé par les paires WX, XY ou YZ ou les triplets WXY ou XYZ, ce qui signifie qu’une séquence de deux (ou trois) octets codant un caractère unicode ne peut être contenu dans une séquence codant un autre caractère. Cela permet des remplacements de séquences d’octets représentant des caractères unicode en étant sûr de ne pas en altérer d’autres. Mais actuellement, les langages de programmation manipulent eux-mêmes les chaînes UTF-8.

La lettre U (point de code 85, 0x55 en hexadécimal) est codée 01010101. Elle pourrait théoriquement être codée sur deux octets 11000001 10010101. Ce n’est pas permis, toutes les possibilités théoriques vues ci-dessus ne sont donc pas légales.

Sauf pour les textes codés uniquement en ASCII (inférieur à 128), le codage utilise nécessairement des signes typographiques utilisant deux ou trois octets. Le codage UTF-8 d’un fichier-texte en français compte environ 6% d’octets de plus d'un caractère, les lettres accentuées prenant deux octets, certains signes typographiques (tiret (semi-)cadratins, puces...) en valant trois.

En cyrillique, arabe, grec monotonique, hébreu et turc, le codage en UTF-8 prendra systématiquement deux octets (trois pour le thaï), alors que les codages iso8859-5, -6, -7, -8, -9 et -11 ne prennent qu’un octet.

De la même manière, les encodages spécifiques aux idéogrammes (ISO2022, GBK, Big5, JIS) prennent deux octets par signe, pour trois en UTF-8.

Les codages non UTF-8 peuvent donc rester pertinents pour les alphabets non latins ou des textes en idéogrammes. C’est moins vrai pour les documents compressés comme ODT, ODS, XLSX ou DOCX.

Vous trouverez sur ce site un tableau Unicode/UTF/HTML (1,2Mo) assez complet, ainsi que les idéogrammes CJK (javascript, l’affichage n’est pas immédiat). Il est également question d’Unicode/UTF-8 sur la page python ; pour un codage d’un octet par caractère d’une dizaine d’alphabets, voir ISO8859.

Doublets Unicode

Certains caractères identiques ou très proches disposent de deux codages différents. Par exemple :

En pratique

Les octets du début d’un codage UTF-8 peuvent facilement être repérés dans un éditeur hexadécimal, commençant par :

Voici comme se code en UTF-8 la phrase : Ça c’est 25€ 𝄞 (chaque paire de chiffres hexadécimaux représente un octet, d’une valeur de 0 à 255).

C3 87 61 20 63 E2 80 99 65 73 74 20 32 35 E2 82 AC 20 F0 9D 84 9E 0A
Ç     a     c  ’        e  s  t     2  5  €           𝄞

Retrouver le point de code à partir du codage UTF-8

C387 représente deux octets, écrit sous forme binaire 1100'0011 1000'0111

1100'0011 1000'0111 donne le binaire 1100'0111, soit C7 ou 199, à savoir le point de code pour Ç

De la même manière, F0 9D 84 9E s’écrit en binaire 1111'0000 1001'1101 1000';0100 1001';1110.

On en extrait 000 011101 000100 011110, soit le binaire 1'1101 0001’0001'1110, l’hexadécimal 0x1D11E ou le décimal 119070, le point de code pour la clé de sol 𝄞.

Coder un point de code en UTF-8

Le symbole € (EUR) a pour point de code 8364, soit 20AC en hexadécimal, et en binaire:

Octets utilisés en UTF-8

Seuls 220 octets sont utilisés / acceptés par l’encodage UTF-8 :

Sont donc utilisés les octets 32 à 247 et les caractères de formatage 9 (tab, \t), 10 (nouvelle ligne en Unix et OSX, \n), 11 (tab vert, \v), 12 (fin de page, \f) et 13 (fin de paragraphe Amiga et Mac avant OSX, \r) ; Les systèmes issus de Digital Research (DOS et Atari) utilisent 13+10 (\r\n).