Chapitre 14 : Les fichiers

Introduction

Dans le chapitre 2, nous avons vu que les variables étaient des objets comparables à des tiroirs dans lesquels on pouvait déposer des données de différents types (nombres entiers, chaînes de caractères, etc…). Mais lorsque nous fermons notre programme, ces variables qui sont créées dans la RAM, c’est-à dire la mémoire vive de l’ordinateur, disparaissent corps et âmes. Il ne sert donc à rien d’y stocker des données que l’on souhaite conserver après la fermeture du programme puisque de toute façon, elles seront perdues. Comment faire alors?

La seule solution consiste à stocker les données que l’on souhaite conserver dans des fichiers qui se trouvent non pas dans la mémoire vive de l’ordinateur mais sur le disque dur.

files

Utilité d’un fichier

Prenons un exemple concret pour illustrer mon propos :

prenom = input("Entrez votre prénom: ")
print("Votre prénom est {}".format(prenom))

Votre prénom est Maxence

Dans ce premier bout de code, le programme demande à l’utilisateur de renseigner son prénom grâce à la fonction input(). La chaîne de caractères est ensuite stockée dans la variable prenom. Mais dès que nous quittons le programme, la variable prenom avec la chaîne de caractères Maxence, disparaît.

À présent, nous allons stocker le prénom de l’utilisateur dans un fichier conservé dans le répertoire courant sur le disque dur :

prenom = input("Entrez votre prénom: ")
file_ = open("utilisateur", 'w')
file_.write(prenom)
file_.close()
file_ = open("utilisateur", 'r')
first_name = file_.read()
file_.close()
print("Votre prénom est {}".format(first_name))

Votre prénom est Fulgent

Dans ce deuxième bout de code, j’ai créé sur mon disque dur (plus précisément dans le répertoire courant qui se nomme /home/benoit), un fichier utilisateur. Ce fichier récupère le prénom entré par l’utilisateur à savoir Fulgent. Le fichier a été créé en mode écriture (‘w’ = write). Ensuite, j’ai fermé le fichier et je l’ai réouvert en mode lecture (‘r’). J’ai stocké le prénom dans une variable intitulée first_name. J’ai fermé le fichier et j’ai fait appel à la fonction print() pour afficher le prénom.

Le fichier créé dans mon répertoire courant /home/benoit

utilisateur_2

Maintenant, je ferme le programme. La variable first_name qui stockait le prénom Fulgent a certes disparu mais comme j’ai pris soin de conserver l’information dans un fichier enregistré dans le répertoire courant sur mon disque dur, je peux très facilement rouvrir ce dernier et récupérer le prénom. Action!

file_ = open("utilisateur", 'r') # Ouverture du fichier en mode lecture
first_name = file_.read() # Stockage du contenu du fichier dans une variable
file_.close() # Fermeture du fichier
print("Votre prénom est {}".format(first_name))

Votre prénom est Fulgent

Mission accompli! Fulgent est toujours en vie.

L’objet-fichier _io.TextIOWrapper

Les fichiers peuvent être manipulés grâce à une interface qu’on appelle objet-fichier. Si on fait print(file_), on obtient ceci :

_io.TextIOWrapper name=’utilisateur’ mode=’r’ encoding=’UTF-8′

Dans le code ci-dessus, file_ est donc un objet de type _io.TextIOWrapper qui ouvre un fichier dont le nom est utilisateur, en mode lecture (‘r’). L’encodage est UTF-8.

Les différents modes d’ouverture

Le mode lecture (‘r’)

Le mode lecture (‘r’) est le mode d’ouverture par défaut c’est-à-dire que vous n’êtes pas obligé de le préciser :

file_ = open("utilisateur")

Le mode lecture permet d’appliquer plusieurs méthodes d’extraction de données que je vais vous présenter dans cet article.

Le mode écriture (‘w’) avec effacement préalable du fichier

‘w’ signifie write. Lorsqu’on utilise ce mode:

  • S’il n’existe pas, le fichier est d’abord créé et il s’agit d’un fichier vide.
  • Si le fichier existe déjà, celui-ci est vidé de son contenu au préalable et grâce à la méthode write(), on peut y écrire de nouvelles données.

Mon fichier utilisateur contient actuellement le prénom Fulgent. Je vais le remplacer par le prénom Toufik.

prenom = input("Entrez votre prénom: ")
file_ = open("utilisateur", 'w')
file_.write(prenom)
file_.close()
file_ = open("utilisateur", 'r')
first_name = file_.read()
file_.close()
print("Votre prénom est {}".format(first_name))

Entrez votre prénom: Toufik
Votre prénom est Toufik

Le contenu de mon fichier a été modifié. Fulgent a disparu et Toufik a pris sa place :

toufik

Le mode ajout (‘a’)

‘a’ signifie append. L’ouverture du fichier en mode ajout va créer un nouveau fichier vide de tout contenu si celui-ci n’existe pas. Si le fichier existe déjà, le mode ‘a’ permet l’écriture dans le fichier à la suite des données déjà présentes. Le contenu du fichier n’est donc pas écrasé au préalable.

prenom = input("Entrez votre prénom: ")
file_ = open("utilisateur", 'a')
file_.write(prenom)
file_.close()
file_ = open("utilisateur", 'r')
first_name = file_.read()
file_.close()
print("Le contenu du fichier est {}".format(first_name))

Entrez votre prénom: Helmut
Le contenu du fichier est ToufikHelmut

ToufikHelmut

Eh! Mais keskispass? ToufikHelmut!! C’est quoi le blème?

Il n’y a pas de blème. Le fichier est ouvert en mode append donc les nouvelles données sont écrites à la suite de celles déjà présentes. Si on veut que le nouveau prénom soit écrit sur une nouvelle ligne, alors il faut prendre soin de rajouter un caractère de saut de ligne ‘\n’. C’est ce que je fais à la troisième  et à la huitième ligne du code ci-dessous.

prenom = input("Entrez votre prénom: ")
file_ = open("utilisateur", 'a')
file_.write(prenom + '\n') # Rajout d'un saut de ligne
file_.close()
file_ = open("utilisateur", 'r')
first_name = file_.read()
file_.close()
print("Le contenu du fichier est:\n{}".format(first_name))

Entrez votre prénom: Toufik
Le contenu du fichier est:
Toufik

>>>
Entrez votre prénom: Helmut
Le contenu du fichier est:
Toufik
Helmut

Vérifions le fichier en question. Nous constatons que cette fois-ci, Helmut a bien été rajouté sur une nouvelle ligne:

helmut

Les modes d’ouverture de fichiers binaires

Dans le prochain chapitre, nous verrons qu’il est parfois nécessaire d’ouvrir des fichiers binaires. Pour ce faire, il existe des modes d’ouverture en binaire :

  • Le mode lecture : ‘rb’
  • Le mode écriture avec effacement préalable du contenu : ‘wb’
  • Le mode ajout : ‘ab’

La fonction intégrée open()

Lorsqu’on créé un objet-fichier, l’ouverture du fichier se fait grâce à la fonction intégrée open().

prenom = input("Entrez votre prénom: ")
file_ = open("utilisateur", 'a')

Refermer un fichier à l’aide de la méthode close()

Après avoir travaillé sur les données d’un fichier, il est nécessaire de refermer ce dernier afin qu’il puisse être disponible pour d’autres utilisations. C’est exactement comme un livre… Lorsque vous avez fini votre lecture, vous ne reposez pas le livre ouvert dans votre bibliothèque! Vous le refermez d’abord, n’est-ce pas?

Cette opération s’effectue grâce à la méthode close() que vous avez découverte dans les différents codes de cet article. Il ne faut pas oublier de refermer un fichier.

Nous verrons dans un prochain paragraphe qu’il existe une autre méthode d’ouverture avec une syntaxe un peu particulière (with open() as). Elle est très intéressante car elle permet de s’affranchir de la méthode close() grâce à l’indentation.

Écrire dans un fichier grâce la méthode write()

La méthode write(), appliquée sur un objet-fichier, permet d’écrire dans un fichier.

file_.write(prenom + '\n') # Écriture dans le fichier

Extraire les données d’un fichier pour les stocker dans une variable

Après avoir ouvert un fichier en mode lecture (‘r’), on peut appliquer sur l’objet-fichier diverses méthodes d’extraction de données.

La méthode read()

Dans les codes précédents, j’ai utilisé la méthode read(). Cette dernière extrait la totalité du contenu du fichier qu’elle retourne sous la forme d’une chaîne de caractères.

La méthode readline()

Cette méthode ne lit qu’une seule ligne à la fois et ne prend pas en compte le caractère de fin de ligne. Elle retourne une chaîne de caractères.

file_ = open("utilisateur", 'r')
first_name = file_.readline()
file_.close()
print("Le contenu du fichier est:\n{}".format(first_name))

Le contenu du fichier est:
Toufik

>>> print(file_.readline())
Helmut

>>> print(file_.readline())
Kevin

La méthode readlines()

La méthode readlines() extrait la totalité du fichier et retourne non pas une chaîne de caractères mais une liste sur laquelle il est possible ensuite d’effectuer une itération.

file_ = open("utilisateur", 'r')
first_name = file_.readlines()
file_.close()
print("Le contenu du fichier est:\n{}".format(first_name))

Le contenu du fichier est:
[‘Toufik\n’, ‘Helmut\n’]

À présent, grâce à une boucle for, je peux par exemple appliquer sur chaque élément de la liste, la méthode lower() pour mettre les prénoms en minuscules.

file_ = open("utilisateur", 'r')
first_name = file_.readlines()
file_.close()
file_ = open("utilisateur", 'w')
for i in first_name:
    file_.write(i.lower())
file_.close()

Les majuscules initiales ont disparu!

lower

La syntaxe with open() as

Dans la mesure du possible, je vous conseille vivement d’utiliser cette syntaxe pour ouvrir vos fichiers car elle a un gros avantage : il n’y a pas besoin d’utiliser la méthode close() pour refermer le fichier. Cette opération est effectuée automatiquement, à la sortie du bloc indenté. with open() as fonctionne comme ceci:

with open("fichier", 'mode') as objet_fichier:
    variable = objet_fichier.readlines() # BLOC INDENTÉ

Reprenons le code précédent et utilisons cette nouvelle syntaxe pour mettre Toufik et Helmut en majuscules à l’aide de la méthode upper():

with open("utilisateur", 'r') as file_:
    first_name = file_.readlines()
with open("utilisateur", 'w') as file_:
    for i in first_name:
        file_.write(i.upper())

TH

Vous constatez que tous les file_.close() ont disparu. Ils sont devenus inutiles. Les étourdis ne risquent donc pas d’oublier de refermer un fichier! Personnellement, j’utilise presque toujours cette syntaxe.

Conclusion

Les fichiers sont nécessaires pour conserver des données avant de quitter une application et pouvoir les réutiliser par la suite. Dans la deuxième partie de ce chapitre, nous ferons connaissance avec le module os et le module pickle.