Codage des caractères
Comment éviter les erreurs d'encodage ?
Programme
Notions | Compétences | Remarques |
---|---|---|
Représentation d'un texte en machine. Exemples des encodages ASCII, ISO-8859-1, Unicode |
Identifier l’intérêt des différents systèmes d'encodage. Convertir un fichier texte dans différents formats d'encodage |
Aucune connaissance précise des normes d'encodage n'est exigible |
Terminal Linux
Activité 1 - Introduction à l'encodage des caractères
Dans le terminal Linux ci-dessus :
- Insert la chaîne de caractère "test" dans un fichier
test.txt
:echo 'test' > test.txt
- Utilise la commande suivante pour connaître le système d'encodage du fichier créé (charset) :
file -i test.txt
- Effectue les mêmes opérations avec la chaîne de caractère "testé".
Pourquoi cette différence d'encodage entre ces 2 fichiers ? C'est quoi us-ascii et UTF-8 ?
La norme ASCII
La norme ASCII
Le standard ACSII pour American Standard Code for Information Interchange a été créé en 1960 aux États-Unis.
Les caractères sont codés sur 7 bits, soit sur 127 «points de code» (nombres associés aux caractères).
Représentation du texte
Activité 2 - Décodage de textes décodés en ASCII
Dans le terminal linux en haut de la page :
- Afficher le contenu hexadécimal du fichier
networking.sh
:od -t x1 networking.sh
- Utiliser le tableau ci-desous pour traduire les 11 premiers caractères (21, 23, ..., 68).
- Vérifier votre résultat en affichat le contenu du fichier :
cat networking.sh
Les normes ISO 8859-xx
Les normes ISO 8859-xx
Lorsque d'autres personnes que des états-uniens ou des anglais ont voulu s'échanger des données faisant intervenir du texte, certains caractères (é, è, à, ñ, Ø, Ö, β, 漢...) étaient manquants. Les 127 caractères de l'ASCII étaient largement insuffisants. Il a donc été décidé de passer à... 256 caractères ! Il suffisait pour cela de coder les caractères non plus sur 7 bits mais sur 8 bits.
Ainsi naquît, après de nombreuses modifications successives (la dernière en date rajoutant par exemple le symbole €), la célèbre table ISO 8859-15, dite aussi Latin-9 :
Autres exemples
Les codes sont donnés en hexadécimal :
- le caractère € correspond au code hexadécimal A4, donc au nombre décimal 164.
- le caractère A correspond au code hexadécimal 41, donc au nombre décimal 65.
Les caractères ASCII y ont été inclus avec leur même code, ce qui rendait cette nouvelle norme rétro-compatible.
Parfait, mais comment font les Grecs pour écrire leur alphabet ? Pas de problème, il leur suffit d'utiliser... une autre table, appelée ISO-8859-7 :
On retrouve les caractères universels hérités de l'ASCII, puis des caractères spécifiques à la langue grecque... oui mais les Thaïlandais alors ?
Pas de problème, ils ont la ISO-8859-11 :
Évidemment, quand tous ces gens veulent discuter entre eux, les problèmes d'encodage surviennent immédiatement : certains caractères sont remplacés par d'autres.
Que fait un logiciel à l'ouverture d'un fichier texte ?
Il essaie de deviner l'encodage utilisé... Parfois cela marche, parfois non.
Normalement, pour un navigateur, une page web correctement codée doit contenir dans une balise meta
le charset
utilisé.
Mais parfois, il n'y a pas d'autre choix pour le logiciel d'essayer de deviner l'encodage qui semble être utilisé.
Activité 3 - Identifier un encodage
Le fichier texte représenté par les octets ci-dessous est-il encodé en ASCII ou en Latin-9 ?
4c 79 63 e9 65 58 50
C'est du Latin-9, car le point de code e9
n'existe pas en ASCII. Le fichier texte contient le mot "LycéeXP"
Activité 4 - Limites des normes ISO-8859
Dans le terminal linux :
- Crée le fichier texte contenant "LycéeXP" :
echo "LycéeXP" > test.txt
- Convertis-le en ISO8859-15 :
iconv -t ISO-8859-15 test.txt -o test.txt
- Affiche le :
cat test.txt
Conclusion sur les normes ISO-8859
Comme tu peux le constater, les normes ISO-8859 étant multiples, elles sont souvent sources de problèmes d'affichage...
La normalisation UTF
La normalisation UTF
En 1996, le Consortium Unicode décide de normaliser tout cela et de créer un système unique qui contiendra l'intégralité des caractères dont les êtres humains ont besoin pour communiquer entre eux.
Ils créent l'Universal character set Transformation Format : l'UTF. Ou plutôt ils en créent... plusieurs :
- l'UTF-8 : les caractères sont codés sur 1, 2, 3 ou 4 octets.
- l'UTF-16 : les caractères sont codés sur 2 ou 4 octets.
- l'UTF-32 : les caractères sont codés sur 4 octets.
Pourquoi est-ce encore si compliqué ? En UTF-32, 32 bits sont disponibles, soit \(2^{32}=4294967296\) caractères différents encodables.
C'est largement suffisant, mais c'est surtout très très lourd !
D'autres encodages plus légers, mais plus complexes, sont donc proposés.
Le cas particulier de l'UTF-8
Le principe de l'UTF-8 est qu'il est adaptatif : les caractères les plus fréquents sont codés sur un octet, qui est la taille minimale (et qui donne le 8 de UTF-8). Les autres caractères peuvent être codés sur 2, 3 ou 4 octets au maximum.
L'encodage des caractères avec Python
Encodage des caractères avec Python
- La fonction
ord(caractere)
renvoie le nombre entier Unicode associé au caractère.
>>> ord('à') 224
- La fonction
chr(nombre)
renvoie le caractère codé par l'entier Unicode nombre.>>> chr(224) 'à'
Activité 5 - Réponse à une question existentielle...
** Mais pourquoi donc le caractère é
en UTF-8 devient-il é en ISO 8859-15 ?!
Q1. Grâce à python, écrire en binaire le nombre associé au caractère é
en UTF-8.
Rappel sur le binaire en python
La fonction bin()
convertit un entier en binaire.
Solution
>>> ord('é')
233
>>> bin(233)
'0b11101001'
é
est associé au nombre 11101001
.
Q2. D'après l'explication de fonctionnement de l'encodage adaptatif de l'UTF-8 (voir ci-dessus), les 8 bits nécessaires à l'encodage de é
en UTF-8 doivent être «encapsulés» dans 2 octets de la forme 110XXXXX 10XXXXXX
, où les onze X
représentent les 11 bits d'information disponibles. Écrire ces 2 octets en complétant si nécessaire avec des 0
à gauche.
Solution
Sur 11 bits, le nombre 11101001
va s'écrire 00011101001
. En séparant ces 11 bits en deux groupes de 5 bits et 6 bits (00011
et 101001
), et en les encapsulant, on obtient les deux octets 11000011 10101001
.
Q3. Convertir les deux octets obtenus en notation décimale puis en hexadécimale.
Rappel sur le décimal et hexadécimal en Python
- La fonction
int('monNombreBinaire', 2)
convertit un binaire en entier.>>> int('11000011', 2) 195
- La fonction
hex(nombre)
convertit nombre en hexadécimal.>>> hex(169) '0xa9'
Solution
>>> int('11000011', 2)
195
>>> hex(195)
'0xc3'
>>> int('10101001', 2)
169
>>> hex(169)
'0xa9'
Q4. Conclusion : Si un logiciel considère à tort que les deux octets servant à encoder le é
en UTF-8 servent à encoder deux caractères en ISO 8859-15, quels seront ces deux caractères ?
Activité 6 - Un peu de cryptographie
On souhaite chiffrer (chiffrer est le mot utilisé en cryptographie pour crypter) le mot "BONJOUR"
avec la clé "LYCEEXP"
. Le chiffrement retenu est un chiffrement par XOR, ce qui signifie qu'on va effectuer un XOR (^) entre les deux nombres associés aux lettres.
Exemple :
- la lettre
'B'
va être chiffrée grâce au'L'
. - Le code ASCII de
'B'
est 66. (on le sait carord('B')
renvoie 66 ) - Le code ASCII de
'L'
est 76. (on le sait carord('L')
renvoie 76 ) - 66 ^ 76 vaut 14.
- Le «caractère» associé à 14 est
'\x0e'
(on le sait carchr(15)
renvoie'\x0e'
)
Le premier caractère du mot chiffré sera donc '\x0e'
Q1. Écrire une fonction chiffre
qui prendra en paramètre un mot mot_clair
et un mot de passe cle
de même taille que mot_clair
et qui renvoie la chaîne de caractères obtenue en XORant mot_clair
avec cle
.
Solution
1 2 3 4 5 6 |
|
Q2. Grâce à la fonction ci-dessus, chiffrer le mot "BONJOUR"
avec la clé "LYCEEXP"
.
Solution
>>> chiffre("BONJOUR", "LYCEEXP")
'\x0f\x0e\x1b\x18\x06\x14\x11'
Q3. Reprendre la chaîne de caractères précédemment obtenue et la rechiffrer à nouveau avec la clé "LYCEEXP"
. Que constate-t-on ?
Solution
>>> chiffre('\x0f\x0e\x1b\x18\x06\x14\x11', "LYCEEXP")
'BONJOUR'
Q4. Montrer que (a^b)^b = a
avec les portes logiques.
Solution
Q4. Résoudre le Pydéfi La clé endommagée
Solution
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
Pour aller plus loin - images, sons et vidéos
# Tests
(insensible à la casse)(Ctrl+I)