Chapitre 07
Les fichiers
Introduction
En Python, l'accès aux fichiers est assuré par l'intermédiaire d'un objet-fichier, un type de données dédié aux accès aux fichiers, qui est créé par un appel à la fonction open().
Cette fonction s'utilise ainsi :
unfichier = open(nomfichier[, mode][, encoding='xxx'])
- le premier argument est une chaîne contenant le nom du fichier à ouvrir
- le second argument est une chaîne précisant le mode d'ouverture :
- "w" (write) indique un mode en écriture,
- "r" (read) indique un mode en lecture (mode par défaut si argument omis),
- "a" (append) indique un mode en ajout.
- le troisième argument est une chaîne indiquant l'encodage des caractères du fichier (par défaut spécifique au système d'exploitation). On utilise en général utf-8, ou latin1, ou ascii.
Notons qu'en mode "w", le fichier est créé et que s'il préexistait, l'ancien est effacé et remplacé par le nouveau.
Lorsque les opérations sur un fichier sont terminées, il faut le fermer par un appel à sa méthode close() qui permet de libérer les ressources allouées pour la gestion de l'accès au fichier et de s'assurer que les données stockées par le système d'exploitation dans des zones mémoire tampons sont effectivement écrites sur le disque.
unfichier.close()
Avant de passer à un exemple concret, créez un fichier dans un éditeur de texte que vous enregistrerez dans votre répertoire avec le nom "villes.txt", par exemple :
Sfax
Tunis
Sousse
Nabeul
Lecture d'un fichier et les méthodes open(), read() et close()
Ensuite, testez cet exemple :
f = open('villes.txt', 'r')
print(f.read())
# renvoie
# Sfax
# Tunis
# Sousse
# Nabeul
f.close()
La première ligne ouvre le fichier "villes.txt" en lecture seule (ceci est indiqué avec la lettre r). Remarquez que le fichier n'est pas encore lu, mais simplement ouvert. La méthode read() sur l'objet f dans la deuxième ligne, retourne sous la forme d'une chaîne de caractères toutes les lignes du fichier. Enfin, on applique la méthode close() sur l'objet f, afin de fermer le fichier.
La méthode readlines()
Voici maintenant un deuxième exemple de lecture d'un fichier avec Python tout en utilisant la méthode readlines() qui retourne une liste contenant toutes les lignes du fichier.
f = open('villes.txt', 'r')
lignes = f.readlines()
print(lignes)
# renvoie ['Sfax\n', 'Tunis\n', 'Sousse\n', 'Nabeul']
for ligne in lignes:
print(ligne)
# renvoie
# Sfax
# Tunis
# Sousse
# Nabeul
Il est à noter que la liste lignes contient le caractère \n à la fin de chacun de ses éléments, ce qui correspond au saut de ligne.
La méthode readline()
La méthode readline() (sans s) lit une ligne d'un fichier et la renvoie sous forme d'une chaîne de caractères. À chaque nouvel appel de readline(), la ligne suivante est renvoyée. Associée à la boucle while, cette méthode permet de lire un fichier ligne par ligne.
f = open('villes.txt', 'r')
ligne = f.readline()
while ligne != "":
print(ligne)
ligne = f.readline()
Les méthodes seek() et tell()
Les méthodes seek() et tell() permettent respectivement de se déplacer au n-ième caractère (plus exactement au n-ième octet) d'un fichier et d'afficher où en est la lecture du fichier, c'est-à-dire quel caractère (ou octet) est en train d'être lu.
>>> f = open('villes.txt', 'r')
>>> f.readline()
'Sfax\n'
>>> f.tell()
6
>>> f.readline()
'Tunis\n'
>>> f.tell()
13
>>> f.seek(0)
0
>>> f.readline()
'Sfax\n'
>>> f.close()
On remarque qu'à l'ouverture d'un fichier, le tout premier caractère est considéré comme le caractère 0 (tout comme le premier élément d'une liste). La méthode seek() permet facilement de remonter au début du fichier lorsque l'on est arrivé à la fin ou lorsqu'on en a lu une partie.
Lecture/écriture dans un fichier binaire
Le module pickle permet d'écrire/lire des données de type quelconque. Le fichier doit être ouvert en binaire, en écriture ('wb') ou en lecture ('rb'). Après import pickle, la syntaxe est :
pickle.dump(obj, nomfichier) (enregistrer obj)
et
obj = pickle.load(nomfichier) (lire obj)
>>> d={1:'un',2:'deux'}
>>> type(d)
<class 'dict'>
>>> f=open('test.dat','wb')
>>> import pickle
>>> pickle.dump(d,f)
>>> f.close()
>>> f=open('test.dat','rb')
>>> x=pickle.load(f)
>>> x
{1: 'un', 2: 'deux'}
>>> type(x)
<class 'dict'>
Itérations directement sur les fichiers
Sous Python, un fichier est une structure itérable ; il est donc possible de parcourir un fichier grâce à la boucle for de la manière suivante :
>>> f = open('villes.txt', 'r')
>>> for ligne in f:
print(ligne)
Sfax
Tunis
Sousse
Nabeul
>>> f.close()
Écriture dans un fichier
Voici un exemple pour écrire dans un fichier :
>>> L=['Python','C++','Java']
>>> f=open('langage.txt','w')
>>> for x in L:
f.write(x)
>>> f.close()
Le contenu du fichier langage.txt est PythonC++Java. Ainsi, après avoir initialisé la liste L, nous avons ouvert un fichier mais cette fois-ci en mode écriture (avec le caractère w). Ensuite, on a balayé cette liste à l'aide d'une boucle. À chaque itération, nous avons écrit chaque élément de la liste dans le fichier et ceci grâce à la méthode write() qui s'applique sur l'objet f. Enfin, on a fermé le fichier avec la méthode close().
Exercices avec corrigés
Énoncés
Écrire un programme Python qui ouvre un fichier en lecture, ouvre un deuxième fichier en écriture et copie le premier fichier dans le deuxième tout en rajoutant au début de chaque ligne du deuxième fichier le nombre de mots que comporte cette ligne.
Exemple :
Fichier source
Apprendre à programmer
Python est un langage de programmation
Fichier destination
3 Apprendre à programmer
6 Python est un langage de programmation
Calculer tous les nombres premiers inférieurs à 103. Ces nombres seront mis par lignes de dix (séparés par des virgules sauf pour le dernier élément) dans un fichier nommé « premier.txt ».
Par exemple, la première ligne de mon fichier est : 2, 3, 5, 7, 11, 13, 17, 19, 23, 29.
Calculer tous les nombres premiers inférieurs à 106. Ces nombres seront mis par lignes de dix (séparés par des virgules) dans dix fichiers traitant des tranches de longueur 105.
Par exemple, la première ligne de mon fichier "Tranche8.txt" est :
800011, 800029, 800053, 800057, 800077, 800083, 800089, 800113, 800117, 800119
Créer un programme Python qui à partir d'un fichier source "source.txt" contenant plusieurs lignes formées par des parenthèses génère un fichier destination "destination.txt" qui pour chaque ligne du fichier source répond par :
- "YES" si l'expression est bien parenthésée
- "NO" si ce n'est pas le cas.
Exemple :
- Si le fichier "source.txt" contient les expressions suivantes :
(()())
))(
))(( - alors le fichier destination contiendra :
YES
NO
NO
Écrire une fonction concat(fichier, fichier1, fichier2) concaténant les fichiers de noms fichier1 et fichier2 en un seul fichier de nom fichier et retournant 0 si tout s'est bien passé, 1 en cas d'erreur.
Écrire une fonction coder(d, fichier1, fichier2) qui copie le fichier de nom fichier1 dans le fichier de nom fichier2 tout en remplaçant chaque caractère c de fichier1 par le caractère de code ASCII chr((ord(c) + d) modulo 256).
Indication :
Vous pouvez utiliser les fonctions prédéfinies ord et chr avec :
- ord(c) : renvoie le code ASCII du caractère c
- chr(x) : renvoie le caractère ayant comme code ASCII l'entier x
Par exemple : ord('a') = 97 et chr(97) = 'a'.
Écrire une fonction countFreq(fichier1, fichier2) qui étant donné un fichier de nom fichier1 renvoyant dans un deuxième fichier de nom fichier2 contenant le dictionnaire du nombre d'occurrences des caractères du premier fichier.
Exemple :
Si le premier fichier contient la chaîne "programme", alors le deuxième fichier contiendra le dictionnaire suivant : {'a':1, 'r':2, 'm':2, 'e':1, 'o':1, 'p':1, 'g':1}.
Soit un fichier de données structuré en une suite de lignes contenant chacune le nom d'un étudiant, son prénom et son groupe séparés par des virgules.
Exemple : Nom, Prénom, Groupe.
- Écrire une fonction nbrEtudiant(nomFich, grp) renvoyant le nombre d'étudiants du groupe grp dans le fichier de nom nomFich.
- Écrire une fonction insererEtudiant(nomFich, etudiant) qui étant donnés le tuple etudiant formé par un nom, un prénom et un groupe, insérer ce nouvel étudiant dans nomFich en supposant que le fichier est déjà trié relativement à la rubrique NOM.
Écrire une fonction fusion(fichFusion, fichier1, fichier2) qui étant donnés deux fichiers de noms fichier1 et fichier2 contenant des nombres entiers séparés par des espaces et triés dans l'ordre croissant, fusionne dans un troisième fichier de nom fichFusion les deux fichiers de sorte que fichFusion soit trié dans l'ordre croissant.
Corrigés
src = open ('source.txt ','r')
dest = open (' destination.txt ','w')
for ligne in src :
dest.write ( str ( len ( ligne.split ()))+' '+ ligne )
src.close ()
dest.close ()
from math import *
def estPremier (n):
for i in range (2, int ( sqrt (n))+1):
if n%i ==0 :
return False
return True
f= open ('premier.txt ','w')
f.write ( str (2)+',')
j=1
for i in range (3 ,10**3 ,2) :
if estPremier (i):
f.write ( str (i))
j +=1
if j%10==0 :
f.write ('\n')
j=0
else :
f.write (',')
f.close()
from math import *
def verif (k):
if k ==1 :
return False
for i in range (2, int ( sqrt (k)+1)):
if k%i ==0 :
return False
return True
a='Tranche '
x =[]
i=1
while (i <11) :
f= open (a+ str (i -1)+".txt","w")
x.clear ()
for j in range ( int ((i -1) *100000) +1, int(i *100000+1) ):
if verif (j):
x.append (j)
if len (x) ==10 :
for k in range (9):
f.write(str(x[k])+",")
f.write( str(x [9]) +"\n")
x.clear ()
if ( len (x) !=0) :
for k in range ( len(x) -1):
f.write ( str (x[k])+",")
f.write ( str (x[len(x) -1])+"\n")
f.close ()
i=i+1
def estBienParenthese (ch):
nbrOuv =0
for x in ch:
if x== '(':
nbrOuv +=1
elif x== ')':
nbrOuv -=1
if nbrOuv <0:
return False
return nbrOuv ==0
src = open ('source.txt','r')
dest = open ('destination.txt','w')
for ligne in src :
if estBienParenthese ( ligne ):
dest.write ('YES \n')
else :
dest.write ('NO\n')
src.close ()
dest.close ()
def concat ( fichier , fichier1 , fichier2 ):
try :
f1= open ( fichier1 ,'r')
f2= open ( fichier2 ,'r')
f= open ( fichier ,'w')
f.write (f1.read ()+f2.read ())
f1.close ()
f2.close ()
f.close ()
return 0
except :
return 1
def coder (d, fichier1 , fichier2 ):
f1= open ( fichier1 ,'r')
f2= open ( fichier2 ,'w')
ch=f1.read ()
for x in ch:
f2.write ( chr (( ord (x)+d) %256) )
f1.close ()
f2.close ()
import pickle
def countFreq ( fichier1 , fichier2 ):
f1= open ( fichier1 ,'r')
f2= open ( fichier2 ,'wb ')
ch=f1.read ()
d ={}
for x in ch:
if x not in d:
d[x ]=1
else :
d[x ]+=1
pickle.dump (d,f2)
f1.close ()
f2.close ()
def nbrEtudiant ( nomFich , grp):
f,n= open ( nomFich ,'r') ,0
for ligne in f:
nom,prenom,groupe=ligne.replace('\n','').split(',')
if groupe == grp :
n +=1
return n
def insererEtudiant ( nomFich , etudiant ):
f= open ( nomFich ,'r')
L=f.readlines ()
f.close ()
L.append ("")
i= len(L) -1
while etudiant[0] <L[i -1].split(',')[0] and i >0:
L[i]=L[i -1]
i -=1
L[i]=etudiant[0]+','+ etudiant[1]+','+ etudiant[2]+'\n'
f= open ( nomFich ,'w')
f.writelines (L)
f.close ()
def fusion ( fichFusion , fichier1 , fichier2 ):
f1= open ( fichier1 ,'r')
f2= open ( fichier2 ,'r')
f= open ( fichFusion ,'w')
liste1 = list ( map (int ,f1.read().split ()))
liste2 = list ( map (int ,f2.read().split ()))
i,j=0 ,0
while i< len ( liste1 ) and j<len( liste2 ):
if liste1 [i]<= liste2 [j]:
f.write ( str ( liste1[i])+' ')
i +=1
else :
f.write ( str ( liste2[j])+' ')
j +=1
while i< len ( liste1 ):
f.write ( str ( liste1[i])+' ')
i +=1
while j< len ( liste2 ):
f.write ( str ( liste2[j])+' ')
j +=1
f1.close ()
f2.close ()
f.close ()