Introduction à l'informatique

Cours 5

kn@lri.fr
http://www.lri.fr/~kn

Le standard UTF-8

Représentation des textes

Comment sont représentés les textes dans un ordinateur ?

(on ne parle pas ici de documents riches comme des PDFs ou des fichiers .docx ou HTML, mais simplement des fichiers textes)

Exemple de texte réaliste:

" سَلَام, Здравей, ¡Hola!, שָׁלוֹם, Γειά σου, 你好, Góðan daginn, 안뇽, こんにちは, Salut, 👋, … "

Historiquement…

Encodage 1 caractère = 1 octet (8 bits) :

… et pendant ce temps là, ailleurs dans le monde

Encodage multi-octets:

Impossibilité de mettre plusieurs « alphabets » dans un même texte

Chaque logiciel « interprétait » les séquences d'octet de manière prédéfinie

Unicode

Un standard international (ISO) qui donne à chaque caractère un code :
A → 65
B → 66

y → 121

é → 233

α → 945

↯ → 8623

Rajouter un nouvel alphabet ou un nouveau caractère est un processus complexe.

Actuellement 143,859 caractères (154 « alphabets » et symboles, dont les symboles Latins, le Chinois, Arabe, …)

Encodage ?

Unicode permet un maximum de 1,111,998 (donc on a attribué ~ 13% des caractères possibles, on a de la marge).

Mais comment stocker ces codes dans un fichier texte par exemple (qui est une suite d'octets) ?

Rappel:

1 octet → 8 bits → 256 valeurs
2 octets → 16 bits → 65 536 valeurs
3 octets → 24 bits → 16 777 216 valeurs

On pourrait utiliser 3 octets pour chaque caractère :

00 00 41 00 00 42 00 03 b1 … A B α

UTF-8

Universal (Character Set) Transformation Format 8 bit

Encodage

Nombre d'octetsvaleursOctet 1Octet 2Octet 3Octet 4
10-127 0xxxxxxx
2127-2047 110xxxxx 10xxxxxx
32048-65535 1110xxxx 10xxxxxx 10xxxxxx
465536-1114111 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

(dans le derniers cas, certains codes sont inutilisés)

Exemples

A  ⟶  6510  ⟶  0100 00012 (représenté sur un seul octet)
 ⟶  787710  ⟶  0001 1110 1100 01012 (représenté 3 octets) :
11100001 1011 10 11 1000 0101≡ 225 187 133
🐵  ⟶  12805310  ⟶  … ≡ 240 159 144 181
Avantages :

Inconvénients :

Si ça vous est déjà arrivé

Martine écrit en UTF-8

É en Unicode est le caractère 201. C'est plus grand que 127, donc codé sur deux octets : 195 137
En Latin 1 : 195 → Ã, 137 → ©

Beaucoup d'autres choses

Chaînes de caractères

Retour sur les chaînes

Les chaînes de caractères sont le type de données permettant de représenter du texte.

>>> t = 'Bonjour, ça va ?' >>> print(t) Bonjour, ça va ? >>> t + ' oui, ça va !' 'Bonjour, ça va ? oui, ça va !' >>> len(t) 16 >>>

Séquences d'échappement

Que se passe-t-il si on veut insérer un caractère « ' » dans une chaîne ?

>>> 'C'est moi!' File "", line 1 'C'est moi!' ^ SyntaxError: invalid syntax

On doit indiquer que le « ' » ne marque pas la fin de la chaîne. On utilise une séquence d'échappement :

>>> 'C\'est moi!' 'C\'est moi! >>> print('C\'est moi!') C'est moi! >>>

Attention, le programmeur saisit deuxcaractères (\') mais Python n'en retient qu'un seul (').

D'autres séquences d'échappement

Comment saisir un caractère \ dans une chaîne ?
Imaginons qu'on veuille le mettre en dernière caractère d'une chaine :

>>> 'Caractère antislash: \' File "", line 1 'Caractère antislash: \' ^ SyntaxError: EOL while scanning string literal

Il faut aussi échapper le caractère \

>>> 'Caractère antislash: \\' 'Caractère antislash: \\'

Il existe d'autres séquences d'échappement :\n(retour à la ligne), \uxxxx (code Unicode en base 16), …

>>> '\u0041\n\u0042' 'A\nB'

D'autres chaînes

En Python, on peut aussi délimiter une chaîne de caractères par " ou encore par """

>>> """Je peux ... écrire une chaîne ... sur ... plusieurs ... lignes!""" 'Je peux\nécrire une chaîne\nsur\nplusieurs\nlignes!'

Manipulation des chaînes

On peut accéder aux nème caractère d'une chaîne comme si c'était un tableau

>>> t = 'Bonjour' >>> t[3] 'j'

L'opération […] renvoie une chaîne de taille 1 contenant uniquement le caractère ce trouvant à cet endroit.
Par contre, il n'est pas possible de mettre à jour une chaîne :

>>> t[3] = 'X' Traceback (most recent call last): File "", line 1, in TypeError: 'str' object does not support item assignment >>>

Autres opérations

En Python les chaînes sont représentée en UTF-8

La fonction chr(n) renvoie le caractère dont le code Unicode est n.
La fonction ord(s) affiche le code Unicode du premier caractère de la chaîne s

>>> chr(65) 'A' >>> chr(945) 'α' >>> chr(128169) '💩' >>> ord('B') 66 >>> ord('😎') 128526

⚠️: pour les « emoji », il faut que les polices soient installées correctement sinon on risque de voir un caractère de susbtitution « � »

Notations pointée

En Python, certaines opérations ne sont pas des fonctions (comme len(…), ord(…), chr(…)) mais doivent être appelées directement sur la valeur à laquelle on veut appliquer l'opération.
C'est le cas de nombreuses opérations sur les chaînes.

>>> t='Bonjour, ça va ?' >>> t.upper() 'BONJOUR, ÇA VA ?' >>> t.lower() 'bonjour, ça va ?' >>> t.split(' ') ['Bonjour,', 'ça', 'va', '?'] >>> u=['Oui', 'ça', 'va' ] >>> "_".join(u) 'Oui_ça_va'

Attention, il est encore un peu tôt pour justifier de cette notation. Donc on ne l'explique pas pour l'instant.

Fonctions sur les chaînes

Si on a une chaîne t :

Entrées et sorties

Retour sur print

On a utiliser print pour afficher une chaîne de caractères.
En fait on peut passer un nombre arbitraire de valeur à print, qui ne sont pas forcément des chaînes (la fonction str(…) est alors appelée automatiquement).
Toute les valeurs sont affichées, séparées par des espaces.

>>> print('Bonjour', 'ça', 'va','?') Bonjour, ça va ? >>> print(1, 'A', True, [1,2,3]) 1 A True [1, 2, 3] >>>

Lecture et écriture de fichiers

En python, la fonction open(chemin, mode) permet d'ouvrir un fichier pour le lire.

Attention aux erreurs

Les opérations sur les fichiers peuvent lever des exceptions (des erreurs)

On pourra utiliser try/except: pour rattraper certaines de ces erreurs.

Opérations sur les fichiers

Le résultat de open(…) est une valeur spéciale, appelée descripteur de fichier. C'est un objet opaque qui possède de nombreuses opérations. On se limite aux plus simples.
On suppose que dans le répertoire courant, on a un fichier test.txt.

>>> f = open("test.txt", "r") >>> f <_io.TextIOWrapper name='test.txt' mode='r' encoding='UTF-8'> >>> lignes = f.readlines() >>> lignes ['Heureux qui, comme Ulysse, a fait un beau voyage,\n',
'Ou comme cestuy-là qui conquit la toison,\n',
"Et puis est retourné, plein d'usage et raison,\n", 'Vivre entre ses parents le reste de son âge !\n', '\n', 'Quand reverrai-je, hélas, de mon petit village\n', 'Fumer la cheminée, et en quelle saison\n', … ] >>>

L'opération f.readlines() renvoie le tableau de toutes les lignes du fichier f. Les retours à la ligne sont conservés.

Opérations sur les fichiers (2)

>>> for i in range(len(lignes)): ... ligne[i] = ligne[i].upper() >>> lignes ['HEUREUX QUI, COMME ULYSSE, A FAIT UN BEAU VOYAGE,\n', 'OU COMME CESTUY-LÀ QUI CONQUIT LA TOISON,\n', "ET PUIS EST RETOURNÉ, PLEIN D'USAGE ET RAISON,\n", … ] >>> f2 = open ("test2.txt", "w") >>> f2.writelines(lignes) >>> f2.close() >>> # on quitte Python et on est dans le terminal $ ls test.txt test2.txt $ cat test2.txt … PLUS MON LOIR GAULOIS, QUE LE TIBRE LATIN, PLUS MON PETIT LIRÉ, QUE LE MONT PALATIN, ET PLUS QUE L'AIR MARIN LA DOULCEUR ANGEVINE.

Opérations sur les fichiers (3)

L'opération f.writelines(tab) écrit le tableau de chaînes de caractères dans le fichier f. Lorsque l'on a fini, il faut refermer le fichier en appeleant f.close() sinon il se peut que certaines lignes ne soient pas écrites dans le fichier.

Étude de cas

Statistiques

On souhaite écrire un petit programme Python qui compte le nombre de lignes et de caractères dans un fichier.

Le programme

chemin = "test.txt" #Modifier pour changer de fichier try: f = open(chemin, "r") lignes = f.readlines() f.close() nb_car = 0 for i in range(len(lignes)): nb_car = nb_car + len(lignes[i]) print("Il y a", len(lignes), "lignes dans le fichier") print("Il y a", nb_car, "caractères dans le fichier") except FileNotFoundError: print("Le fichier", chemin, "n'existe pas !") except IsADirectoryError: print(chemin, "est un répertoire !") except PermissionError: print("Vous n'avez pas les droits en lecture sur le fichier", chemin) except UnicodeDecodeError: print("Le fichier", chemin, "n'est pas un fichier contenant du texte")

Conclusion

On n'a vu comment représenter des textes (en UTF-8) et lire et écrire des fichiers de façon sommaire.

Les manipulations de chaînes et de fichiers seront un bon prétexte pour continuer à travailler sur les tableaux et les boucles while et for.