Aujourd'hui, je vous propose de nous attarder sur le principe d'encodage des caractères. Bien comprendre comment votre ordinateur encode vos fichiers va vous permettre d'éviter de nombreuses erreurs par la suite. Un des problèmes typique que l'on rencontre lorsque l'on commence à écrire nos premiers fichiers HTML c'est l'apparition de caractères "bizarres" à la place de nos caractères accentués.

Par exemple la phrase :

<p>
    Voici ma première page
</p>

Qui s'affiche de la manière suivante sur le navigateur :

Voici ma premi�re page

Qu'est ce que l'encodage

Le problème en informatique, c'est que notre ordinateur ne travaille pas avec des lettres, mais en binaire (avec des 0 et des 1). Pour votre ordinateur votre page HTML ne ressemble pas à ce que vous voyez au niveau de votre éditeur mais ressemble plutôt à une suite de bits.

Pour un humain :

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Ma page</title>
  </head>
  <body>
    Voici ma première page
  </body>
</html>

Pour un ordinateur :

00111100 00100001 01000100 01001111 01000011 01010100
01011001 01010000 01000101 00100000 01101000 01110100
01101101 01101100 00111110 00001101 00001010 00111100
01101000 01110100 01101101 01101100 00111110 00001101
00001010 00100000 00100000 00111100 01101000 01100101
01100001 01100100 00111110 00001101 00001010 00100000
00100000 00100000 00100000 00111100 01101101 01100101
01110100 01100001 00100000 01100011 01101000 01100001
01110010 01110011 01100101 01110100 00111101 00100010
01110101 01110100 01100110 00101101 00111000 00100010
00111110 00001101 00001010 00100000 00100000 00100000
00100000 00111100 01110100 01101001 01110100 01101100
01100101 00111110 01001101 01100001 00100000 01110000
01100001 01100111 01100101 00111100 00101111 01110100
01101001 01110100 01101100 01100101 00111110 00001101
00001010 00100000 00100000 00111100 00101111 01101000
01100101 01100001 01100100 00111110 00001101 00001010
00100000 00100000 00111100 01100010 01101111 01100100
01111001 00111110 00001101 00001010 00100000 00100000
00100000 00100000 11100111 01100001 00100000 01110110
01100001 00100000 01110100 01110010 11101000 01110011
00100000 01100010 01101001 01100101 01101110 00001101
00001010 00100000 00100000 00111100 00101111 01100010
01101111 01100100 01111001 00111110 00001101 00001010
00111100 00101111 01101000 01110100 01101101 01101100
00111110

Les bits sont organisés par groupe de huit, appellés octet. Chaque octet permet de représenter des valeurs allant de 0 à 255. Du coup, pour votre ordinateur, votre fichier n'est ni plus ni moins qu'une suite de nombres. Pour obtenir des caractères à l'écran il nous suffit donc de créer une table qui fait correspondre à ces différents nombres un caractère de notre alphabet. Il existe plusieurs tables, correspondant à des régions et des alphabets différents.
La table ASCII par exemple, permet de représenter 128 caractères (cet encodage n'utilise que 7 bits sur les 8 disponibles dans un octet). Cette table est suffisante pour les Américains mais ne convient pas forcément pour des pays avec un alphabet plus complet.
Par exemple pour les pays d'Europe de l'Ouest, Windows utilise le système d'encodage Windows 1252, tandis que Mac OS utilisait l'encodage MacRoman. Ces deux systèmes d'encodage reposent sur l'utilisation des 8 bits d'un octet afin de représenter 256 caractères (ce qui est suffisant pour les langages traités) mais certaines lettres ne sont pas forcément à la même position d'une table à l'autre.

La multiplication des tables d'encodage permet du coup de comprendre les problèmes que l'on peut avoir au niveau des caractères spéciaux. Si vous écrivez votre fichier avec un système d'encodage particulier, mais que vous le lisez avec un système encodage différent, certains caractères peuvent se trouver interchangés, ou remplacés par des caractères "bizarres".

Unicode et UTF8

Ces problèmes d'encodage n'étaient pas trop gênant au début parce qu'on ne partageait pas forcément les fichiers entre les pays. Mais avec le développement de l'internet, il a fallu trouver un moyen de communiquer et d'échanger avec des personnes n'ayant pas forcément le même alphabet (et donc la même façon d'encoder les textes). Et c'est ainsi qu'est né l'Unicode, c'est un système qui va permettre des échanges dans tous les langages du monde en créant un système de codage ou tous les caractères auront un identifiant numérique unique. Ce standard couvre plus de 120 000 caractères mais pose alors un problème : comment représenter autant de caractères en binaire.

Une première idée, serait d'utiliser plusieurs octets pour représenter chacun de nos caractères. Le principal inconvénient de cette approche, est que tous les caractères occupent alors plus d'espace rendant les fichiers plus volumineux à échanger. Et c'est là que l'UTF-8 intervient.

UTF-8 est un système d'encodage qui va encoder les caractères en utilisant un nombre variant d'octets. Certains caractères n'occuperont qu'un seul octet alors que d'autres en occuperont plusieurs. Le problème est alors pour l'ordinateur de déterminer sur combien d'octets le caractère est actuellement encodé.

  • Pour commencer l'UTF 8 reprend la table de caractère ASCII pour les 127 premiers caractères.
  • Pour les caractères ayant une valeur supérieure à 127, l'UTF 8 va alors utiliser plusieurs octets en indiquant le nombre d'octets à utiliser à l'aide des premiers bits
    • 110xxxxx 10xxxxxx
    • 1110xxxx 10xxxxxx 10xxxxxx
    • 11110xxx 10xxxxxx 10xxxxxx

Cette méthode est simple est peut être résumé de la manière suivante :

  • Le code de prefix (110, 1110, 11110) permet de déterminer le nombre d'octet à utiliser pour lire le caractère.
  • Les octets commençant par 10 sont des octets de continuation
  • Les octets commençant par 0 représentent un caractère disponible dans la table ASCII (ce qui permet à l'UTF-8 d'être compatible avec l'encodage ASCII).
  • Pour obtenir le nombre il suffit de prendre les bits restant

Par exemple si on lit les octets 01101000 11000011 10101001
Le premier octet commence par un 0 est donne 104 en décimal et correspond donc à h dans la table unicode
Le second octet commence par deux 1, on doit donc prendre les 2 octets et retirer les préfixes :

11000011 10101001
___00011 __101001
00011101001

00011101001 correspond au nombre 233 en décimal et à la lettre é dans la table unicode. Du coup 01101000 11000011 10101001 affichera sur l'écran.

Et l'UTF-16 c'est mieux ?

L'UTF-16 est un encodage qui se base sur le même principe de tailles variables mais qui encode les caractères sur 2 octets par défaut (ce qui double le poid pour l'utilisations des premiers caractères mais peut être plus intéréssant pour certains langages). Cet encodage ne présentera pas un grand intérêt pour l'HTML car Les balises ne sont composées que de caractères en début de table (cet encodage aura tendance à créer des pages plus lourde et ne sera donc pas intéréssant et il en va de même pour l'UTF-32).