Le but de cette séance est de manipuler les fichiers (au sens large).
1. Rappels sur les Fichiers
1.1. Rappels sur les Formats
Un fichier peut utiliser de nombreux formats, sous Linux c’est la commande file
qui peut déterminer le format indépendemment de l’extension. Faire cet exemple
$ echo "TOTO" > toto.mp3 $ file toto.mp3
Ouvrir votre éditeur favori et y écrire un petit texte de plusieurs lignes. Sauvegarder le
fichier sous le nom exemple.txt
, quel est le format de ce fichier ?
Expliquer le résultat de
$ hexdump -C exemple.txt
1.2. Manipulation sous “python“ : Lecture
Voici un premier exemple exemple.py
de lecture de fichier
# Lecture (simple) ligne par ligne with open("exemple.txt", "r") as fichier: for ligne in fichier: print(ligne.strip())
A quoi sert strip()
? Expliquer en quoi cela est une question de format.
1.3. Manipulation sous “python“ : Ajout
Modifier le code précédent pour ajouter une ligne en fin de fichier
qui donne le nombre de lignes NN
du fichier initialement.
Nombre de lignes: NN
On proposera deux solutions
- en réouvrant le fichier pour l’ajout avec
with open("exemple.txt", "a") as fichier:
- en travaillant dans une seule boucle avec
with open("exemple.txt", "r+") as fichier:
Expliquer les différences entre les deux solutions.
1.4. Manipulation sous “python“ : Lecture/Écriture
Écrire un programme elpmexe.py
qui sauvegarde dans le fichier
elpmexe.txt
le contenu du fichier exemple.txt
.
On rappelle que les option pour open
sont ici.
Quel est le coût en utilisation mémoire de votre solution, en fonction
de la taille du fichier exemple.txt
?
2. Accès Bas Niveau
Il est parfois nécessaire d’utiliser des accès bas-niveau pour gérer certaines situation. Dans cette partie, nous allons voir les méthodes concernées.
2.1. Lecture Bas Niveau
On va utiliser la méthode os.open
(donc ne pas oublier de faire import os
).
Nous avons ainsi accès au descripteur de fichier correspondant.
Il faut ici cependant tout gérer, sans le mot-clef with
.
fd = os.open("exemple.txt",os.O_RDONLY) print(fd) # <fd> print(os.getpid()) # <pid> input("Appuyez sur Entrée") octets = os.read(fd,1) input("Appuyez sur Entrée") octets = os.read(fd,1) input("Appuyez sur Entrée") octets = os.read(fd,1) input("Appuyez sur Entrée") os.close(fd)
Avant chaque “Entrée”, afficher les informations correspondantes depuis un (autre) shell
$ cat /proc/<pid>/fdinfo/<fd>
Que signifient les différents champs ?
2.2. Lecture Octet par Octet
Modifier le premier exemple en ajoutant une boucle pour
lire toute une ligne octet par octet, ie jusque octets[0] == '\n'
Compléter ensuite en ajoutant un message message
donnant le nombre
de lignes NN
du fichier initialement, ce message doit être affiché
sur la sortie d’erreur standard avec os.write(2,message)
. Comment
faire également avec la commande print
?
2.3. Lecture de fichier binaire
Il existe sur votre système des fichiers spéciaux, ie des interfaces
en mode fichier avec le noyau.
Commençons par le fichier /dev/random
.
Il faut l’ouvrir en mode binaire en ajoutant b
:
with open("/dev/random", "rb") as fichier:
Reprendre exemple.py
pour afficher le contenu ligne par ligne
de /dev/random
. Que constatez-vous ?
2.4. Application
Nous allons faire du chiffrement avec un masque jetable.
Commencer par obtenir un fichier clef.bin
de 1OMo d’octets aléatoires à partir de /dev/random
.
Écrire un programme masque jetable
qui prend comme paramètre un fichier
à chiffrer et qui applique le masque jetable (le xor se fait avec ^
sur des objets bytes
) en python).
Le résultat est stocké dans le fichier out.bin
(que se passe-t-il si l’on utilise la sortie standard ?)