Adloun

NSI (première) · Chapitre 2 · Exercice de TD

Le mojibake du cours (é au lieu de é) se reproduit en trois lignes

Flottants, booléens et textes · Caractères, encodages et accidents de lecture · niveau 3 (difficile)

Énoncé

Le mojibake du cours (é au lieu de é) se reproduit en trois lignes. (a) Écrire abimer(texte) qui simule la lecture d'un fichier UTF-8 par un logiciel croyant lire du latin-1. (b) Écrire reparer(abime) qui annule l'accident, et expliquer pourquoi c'est possible. (c) Pourquoi l'accident ne provoque-t-il aucune erreur, alors que l'accident inverse (lire du latin-1 en croyant lire de l'UTF-8) en provoque souvent une ?

Corrigé

(a) et (b). Un encodage transforme un texte en octets, un décodage fait l'inverse. L'accident consiste à enchaîner l'encodage d'un encodage et le décodage d'un autre.


def abimer(texte):
    """Simule : ecrit en UTF-8, relu comme du latin-1."""
    return texte.encode("utf-8").decode("latin-1")


def reparer(abime):
    """Annule abimer : chaque caractere redevient son octet."""
    return abime.encode("latin-1").decode("utf-8")

>>> abimer("élève")
'élève'
>>> reparer(abimer("élève"))
'élève'

La réparation marche parce que les deux fonctions sont exactement inverses : latin-1 associe le caractère de point de code à l'octet , pour les valeurs, sans trou. Ré-encoder en latin-1 restitue donc les octets UTF-8 d'origine, octet pour octet, et il ne reste qu'à les décoder correctement.

(c) L'asymétrie. Latin-1 sait décoder n'importe quelle suite d'octets : les valeurs possibles ont toutes un caractère. Aucune erreur n'est donc possible — seulement un résultat absurde. UTF-8, au contraire, a une grammaire : un octet commençant par 110 doit être suivi d'un octet commençant par 10. Une suite d'octets latin-1 quelconque viole vite cette règle, et le décodage lève UnicodeDecodeError.

La leçon : un décodage qui réussit ne prouve rien. Ce n'est pas le programme qui sait dans quel encodage un fichier est écrit ; c'est vous. D'où l'argument encoding obligatoire dans open.

Contrôle : "élève".encode("latin-1").decode("utf-8") lève bien UnicodeDecodeError, tandis que l'accident dans l'autre sens passe sans broncher.

100 % gratuit

Essaie le suivant avec le tuteur

Faire l'exercice suivant avec le tuteur

Sans compte : le cours, 2 minutes de podcast et de vidéo et un exercice avec le tuteur. Pour tout le reste : inscription gratuite en 30 secondes, sans carte bancaire.

Le cours du chapitre · Tous les exercices du chapitre

Exercice suivant avec le tuteur →