Les bases de la programmation


précédentsommaire

Les fichiers

But de ce chapitre

En utilisant ce que nous avons vu dans les cours précédents, vous ne pouvez pas réaliser un programme qui serait capable de conserver ses résultats une fois l'ordinateur éteint. D'autre part, les données doivent être nécessairement fournies par l'utilisateur à chaque exécution du programme. Ces limitations proviennent du type de mémoire utilisé : pour l'instant, vous ne savez traiter que des données stockées en mémoire vive. Or, la mémoire vive est volatile : lorsque l'ordinateur est mis hors tension, tout disparaît !

Ce problème pourrait donc être donc résolu si vous connaissiez les instructions permettant de lire ou d'enregistrer des données dans des mémoires non volatiles, stockées par exemple sur le disque dur ou sur une clé USB, sous la forme de fichiers.

L'objectif de ce cours est de vous décrire précisément les procédures Pascal réalisant ceci.

Notion de fichier

Qu'est-ce qu'un fichier ?

Un fichier est un ensemble de données informatiques stockées en mémoire auxiliaire (disque dur, CD, DVD, clef USB…) possédant un nom, un chemin d'accès et généralement implicitement associé à un format (format image, format de documents, formats de base de données…).

Le terme de mémoire auxiliaire désigne tout support de stockage de l'information d'un ordinateur autre que la mémoire vive.

Le fait qu'un fichier soit toujours stocké sur mémoire auxiliaire a deux conséquences.

Premièrement, les données contenues dans un fichier ne sont pas perdues lorsque l'ordinateur est mis hors tension (contrairement aux données contenues dans les variables d'un programme !).

Deuxièmement, l'accès à des données stockées dans un fichier est considérablement plus lent qu'un accès à des données contenues en mémoire vive.

Nom de fichier

La manière de nommer les fichiers dépend fortement du système d'exploitation. Par exemple, sous Windows, tout fichier possède généralement une extension (.doc, .jpg…) qui permet d'identifier son format.

Chemin d'accès

Le chemin d'accès d'un fichier définit sa localisation sur un périphérique donné. C'est une chaîne de caractères qui définit la suite des répertoires à parcourir pour atteindre le fichier depuis la racine du périphérique.

La manière de décrire un chemin dépend du système d'exploitation. Sous Windows, un chemin est une chaîne de caractères de la forme :

 
Sélectionnez
X:\Répertoire\Répertoire\ ... \Répertoire

X est une lettre définissant le périphérique utilisé.

Par exemple :

 
Sélectionnez
C:\Utilisateurs\Thirion\Documents

Identification d'un fichier par son nom complet

Le nom d'un fichier ne l'identifie pas de manière unique. Par exemple, il peut exister un fichier nommé CV.doc sous

 
Sélectionnez
C:\Utilisateurs\Thirion\Documents

et un autre sous

 
Sélectionnez
C:\Utilisateurs\Einstein\Documents

Pour identifier un fichier de manière unique, il faut utiliser son chemin concaténé avec le nom (simple) du fichier. Par exemple :

 
Sélectionnez
C:\Utilisateurs\Thirion\Documents\CV.doc

désigne le CV de Thirion, alors que :

 
Sélectionnez
C:\Utilisateurs\Einstein\Documents\CV.doc

désigne le CV de Einstein.

J'utiliserai par la suite le terme de nom complet, pour désigner le chemin concaténé avec le nom du fichier.

Format

Le format d'un fichier est un ensemble de conventions définissant la représentation des données qu'il contient : la localisation et le codage des différents types d'informations contenues dans le fichier.

Le fichier en lui-même ne permet pas à coup sûr de retrouver son format de manière immédiate : comme toute chose en informatique, ce n'est qu'une suite de zéros et de uns. Une manière de vérifier si un fichier est bien dans un format donné est de l'ouvrir avec un logiciel adapté à ce format. Si le logiciel gère correctement le fichier, il est certainement dans le bon format (mais ce n'est pas une certitude !). Une autre manière est de scruter l'en-tête du fichier à la recherche d'une signature numérique propre à son format.

Exemple : si je peux ouvrir un fichier avec Word, il s'agit très certainement d'un fichier respectant un des formats acceptés par Word (.doc, .txt…). Au contraire, si j'essaie d'ouvrir avec Word un fichier qui n'est pas dans un format accepté par Word, il se produira probablement n'importe quoi.

Sous Windows, le format d'un fichier est repérable par l'extension (.doc pour un fichier Word, .exe pour un fichier exécutable…). Mais l'extension d'un fichier peut être changée manuellement… L'extension d'un fichier ne donne donc aucune certitude sur son format !

Les fichiers texte

Les fichiers texte sont des fichiers que l'on peut ouvrir avec un éditeur de texte (comme WordPad ou le Bloc-notes) afin de modifier leur contenu.

Ce sont par exemple les fichiers d'extension .txt sous Windows, les fichiers sources d'un programme, les fichiers HTML, etc.).

Un fichier texte est un fichier qui peut être interprété comme une suite de caractères (le plus souvent en code ASCII) affichables à l'écran.

Deux caractères spéciaux servent à coder le passage à la ligne et la fin du fichier.

Les fichiers structurés

Les fichiers structurés sont des fichiers interprétables comme une suite d'enregistrements d'un certain type. Tous les enregistrements sont forcément de même taille.

Les fichiers structurés peuvent être vus comme la représentation d'un tableau en mémoire auxiliaire. Rappelez-vous que tous les éléments d'un tableau doivent être de même type. Les éléments du tableau correspondent ici aux enregistrements.

Certains auteurs utilisent le nom de fichiers séquentiels pour désigner des fichiers structurés. Je trouve ce nom très mal adapté car il porte à confusion. Nous verrons pourquoi un peu plus loin.

Opérations sur les fichiers

Les langages de programmation permettent de :

  • créer des fichiers ;
  • enregistrer des informations dans un fichier : c'est l'accès en écriture ;
  • lire des informations dans un fichier : c'est l'accès en lecture.

Les erreurs d'accès

Le système d'exploitation est responsable de la gestion des fichiers d'un ordinateur. Toute opération sur un fichier se fait donc nécessairement par l'intermédiaire du système d'exploitation. Lorsqu'un programme effectue une opération sur un fichier, il faut que le système d'exploitation autorise cette opération, sans quoi il se produira une erreur d'accès :

Image non disponible

Voilà quelques-unes des erreurs les plus fréquentes :

  • vous faites un accès en lecture sur un fichier qui n'existe pas ;
  • vous faites un accès en lecture sur un fichier, alors que vous n'avez pas de droit de lecture sur ce fichier : ce fichier appartient à un autre utilisateur, c'est un fichier protégé, etc. ;
  • vous faites un accès en écriture sur un fichier, alors que vous n'avez pas de droit d'écriture sur ce fichier ;
  • vous faites un accès en écriture sur un fichier alors qu'un autre programme est en train d'y accéder en lecture ou en écriture ;
  • vous faites un accès en écriture sur un fichier alors que le périphérique qui le contient est plein ;
  • vous faites un accès en lecture ou en écriture « en dehors » du fichier.

Ouverture et fermeture d'un fichier

L'accès à un fichier par programmation fonctionne toujours selon le même principe :

  • avant de lire ou d'écrire des informations dans un fichier, il faut l'ouvrir ;
  • lorsque le traitement du fichier est terminé il faut le fermer.

À quoi sert l'ouverture d'un fichier ?

Ouvrir un fichier sert (entre autres) à informer le système d'exploitation que l'on a l'intention d'y accéder. C'est à ce moment-là que le système peut refuser l'accès au fichier, ce qui provoquera une erreur d'exécution du programme.

À quoi sert la fermeture d'un fichier ?

La fermeture d'un fichier sert (entre autres) à signaler au système d'exploitation que le fichier n'est plus utilisé par le programme, ce qui permettra à un autre programme (éventuellement d'un autre utilisateur) d'y accéder.

Accès direct et accès séquentiel

Il y a deux manières d'accéder à un fichier par programmation : l'accès direct et l'accès séquentiel.

Accès direct

L'accès direct n'est possible que pour des fichiers définis comme une suite de blocs de taille fixe que l'on appelle enregistrements. Il n'est donc possible que pour les fichiers structurés.

Image non disponible

L'accès direct signifie qu'il est possible d'accéder directement à un enregistrement à partir de sa position dans le fichier : lire le énième enregistrement du fichier ou le modifier. Ce type d'accès est par exemple adapté à la gestion des tables d'une base de données.

Accès séquentiel

Dans l'accès séquentiel, une opération de lecture ou d'écriture se fait toujours juste après la dernière partie du fichier lue ou écrite.

Image non disponible

Les fichiers texte n'autorisent que ce type d'accès.

Les fichiers structurés quant à eux autorisent les deux types d'accès (séquentiel ou direct).

Vous comprenez à présent pourquoi le fait d'appeler « fichiers séquentiels » les fichiers structurés est une source de confusion !

Manipulation des fichiers texte

Ouverture d'un fichier texte

L'ouverture d'un fichier texte se fait en lecture, en écriture ou en ajout. Nous ne traiterons pas ici de l'ouverture en ajout.

Si le fichier est ouvert en lecture, il ne peut y avoir que des lectures jusqu'à la fermeture du fichier.

De même, si le fichier est ouvert en écriture, il ne peut y avoir que des écritures jusqu'à la fermeture du fichier.

Opérations sur les lignes

Un fichier texte est normalement organisé en lignes. Les langages de programmation contiennent en général une instruction (ou une procédure) permettant de :

  • lire une ligne du fichier en la recopiant dans une variable de type chaîne de caractères. Cette opération n'est possible que si le fichier est ouvert en lecture. De plus, comme il s'agit d'un accès séquentiel, elle se fait forcément juste après la dernière ligne lue. Sauf si le fichier vient d'être ouvert. Dans ce cas, la ligne lue est nécessairement la première ligne du fichier ;
  • écrire une chaîne de caractères dans une ligne du fichier. De même, cette opération n'est possible que si le fichier est ouvert en écriture et se fait forcément juste après la dernière ligne écrite. Exception pour l'écriture d'une ligne qui suit immédiatement l'ouverture du fichier : ce sera forcément la première ligne du fichier.

Manipulation des fichiers structurés

Ouverture d'un fichier structuré

Pour ouvrir un fichier structuré, il n'est pas nécessaire de préciser si l'on veut ouvrir le fichier en lecture ou en écriture. En effet, avec un fichier structuré, ces deux types d'opérations (lecture et écriture) peuvent être mélangées dans n'importe quel ordre.

Si le fichier n'existe pas avant l'ouverture, il sera créé.

Accès séquentiel

L'accès séquentiel dans un fichier structuré consiste à lire ou à écrire un enregistrement sans préciser sa position. La lecture ou l'écriture se fait nécessairement juste après le dernier enregistrement lu ou écrit. Sauf si le fichier vient juste d'être ouvert. Dans ce cas, l'enregistrement lu ou écrit sera forcément le premier.

Accès direct

Dans l'accès direct, on accède à un enregistrement par sa position dans le fichier. Il est par exemple possible de lire le 25e enregistrement, puis de modifier le 122e. On peut parcourir le fichier dans n'importe quel ordre.

Manipulation de fichiers texte en Pascal

Déclaration

Un fichier texte est représenté en Pascal par le type TextFile. Pour pouvoir manipuler un fichier texte, il faut d'abord déclarer une variable de ce type. Par exemple :

 
Sélectionnez
var f : TextFile;

Dans toutes les explications qui suivent, f désignera le fichier déclaré de cette manière.

Assignation

Avant de pouvoir ouvrir un nouveau fichier texte, il faut d'abord associer la variable fichier au nom du fichier sur le disque. Cela se fait par la procédure AssignFile. Voici, par exemple, comment associer f à un fichier nommé exemple.txt :

 
Sélectionnez
AssignFile(f,'exemple.txt');

Création d'un fichier texte

Ouverture en écriture

Après avoir déclaré une variable de type fichier et assigné cette variable à un nom de fichier, on peut l'ouvrir en écriture. Cela a pour effet de créer un nouveau fichier vide. Attention : s'il existe déjà un fichier de même nom sur le disque, le contenu de ce dernier sera perdu !

L'ouverture en écriture, se fait par la procédure rewrite, comme suit :

 
Sélectionnez
rewrite(f);

Écriture d'une ligne

Dès que le fichier est ouvert en écriture, on peut y écrire du texte en utilisant la procédure writeln. Voici, par exemple, comment créer un fichier texte exemple.txt d'une ligne :

 
Sélectionnez
var f: TextFile;
begin
  assign (f,'exemple.txt');
  rewrite(f);
  writeln (f,'Ceci est un fichier d'une ligne.');
  CloseFile(f); 
end;

La procédure CloseFile appelée à la fin sert à fermer le fichier.

Comme on fait de l'accès séquentiel, une écriture se fait forcément après la ligne écrite juste avant. Donc, après l'exécution du code suivant :

 
Sélectionnez
var f: TextFile;
begin
  assign(f,'exemple.txt');
  rewrite(f);
  writeln(f,'Première ligne du fichier exemple.txt');
  writeln(f,'Deuxième ligne du fichier exemple.txt');
  CloseFile(f);
end;

le fichier exemple.txt contiendra les deux lignes :

 
Sélectionnez
Première ligne du fichier exemple.txt
Deuxième ligne du fichier exemple.txt

Lecture d'un fichier texte

Ouverture d'un fichier texte en lecture

Pour ouvrir un fichier en lecture, on utilise la procédure reset de la manière suivante :

 
Sélectionnez
reset(f);

Comme pour l'ouverture en écriture, il faut que le fichier ait auparavant été assigné à un nom de fichier. Par contre, si ce fichier n'existe pas, cela provoquera une erreur.

Lecture d'une ligne et test de fin de fichier

Pour lire une ligne dans le fichier, on utilise la procédure readln, qui affecte la ligne courante à une variable L de type chaîne de caractères :

 
Sélectionnez
readln(f,L);

Il s'agit ici d'un accès séquentiel, donc une lecture de ligne se fait nécessairement juste après la ligne lue précédemment.

Juste après l'ouverture du fichier, readln transfère la première ligne du fichier dans variable L.

À la deuxième exécution de cette procédure, L contiendra la 2e ligne du fichier et de manière générale, après la énième exécution, L contiendra la énième ligne du fichier.

Bien entendu, on provoquera une erreur d'exécution si l'on essaie de lire au-delà de la fin du fichier. Par exemple, si le fichier exemple.txt ne contient que 10 lignes, la 11e exécution de readln(f,L); provoquera une erreur d'exécution.

Pour éviter cette erreur, il faut utiliser la fonction eof, qui permet de tester si l'on se trouve en fin de fichier. Par exemple, le code suivant permet de lire toutes les lignes du fichier exemple.txt afin d'effectuer un certain traitement sur chaque ligne :

 
Sélectionnez
Var f : TextFile; L : String;
begin
  assign(f,'exemple.txt');
  reset(f);

  while not eof(f) do
  begin
     readln(f,L);
     // Traitement de la ligne L
  end;
  CloseFile(f);

end;

Les fichier structurés en Pascal

Déclaration

Un fichier structuré est un fichier constitué d'enregistrements de même type.

Le type d'un enregistrement est a priori n'importe quel type Pascal de taille fixe. En effet, comme chaque enregistrement doit occuper la même taille en mémoire auxiliaire, on ne peut pas déclarer un fichier constitué d'enregistrements de longueur variable. En particulier, le type String sera interdit et devra être remplacé par le type String[n], qui permet de préciser la taille de la chaîne de caractères.

Pour la suite des explications, nous allons utiliser le type structuré Livre déclaré comme suit :

 
Sélectionnez
Livre =
  record
    Titre : String[100];
    Auteur : String[20];
    AnnéePub : integer;
  end;

Nous pouvons ensuite déclarer un fichier structuré composé d'enregistrements de type Livre comme suit :

 
Sélectionnez
var f : file of Livre;

Remarquez que le type des enregistrements d'un fichier structuré n'est pas forcément un type structuré. On peut par exemple déclarer un fichier d'entiers (file of integer) ou un fichier de caractères (file of char).

Assignation

Tout comme pour les fichiers texte, avant d'ouvrir un fichier structuré il faut associer la variable représentant le fichier à un nom de fichier avec la procédure AssignFile.

Exemple :

 
Sélectionnez
AssignFile(f,'Bibliotheque.dat');

Cette instruction assigne f au fichier de nom Bibliotheque.dat.

Ouverture et fermeture

Pour ouvrir des fichiers structurés, on utilise encore les procédures reset et rewrite. Mais elles n'ont pas la même signification que pour les fichiers texte.

En effet, il sera toujours possible de lire et d'écrire des enregistrements, que le fichier soit ouvert avec reset (ouverture en lecture pour un fichier texte) ou avec rewrite (ouverture en écriture pour un fichier texte).

Pour les fichiers structurés, rewrite n'est pas une ouverture en écriture. Cela signifie seulement que l'on demande au système d'exploitation de créer un nouveau fichier. Avec reset, on demande simplement l'ouverture, sans création d'un nouveau fichier.

Par contre, un fichier ne peut pas être ouvert avec reset s'il n'existe pas. Pour ouvrir un fichier structuré sans savoir auparavant s'il existe ou non, on utilisera la fonction FileExists (fonction permettant de tester l'existence d'un fichier de nom donné) de la manière suivante :

 
Sélectionnez
 if FileExists('Bibliotheque.dat') then
    reset(f)
 else
    rewrite(f);

Écriture séquentielle

L'écriture d'un enregistrement se fait avec la procédure write. Plus précisément, write (f,v) écrit la valeur de la variable v dans le fichier f à la suite du dernier enregistrement lu ou écrit. Bien entendu, la variable doit être de même type que les enregistrements du fichier.

Si le fichier vient d'être ouvert, l'écriture se fait dans le premier enregistrement.

Déclarons par exemple deux structures de type Livre :

 
Sélectionnez
var VB, Gaston : Livre;

Donnons des valeurs à leurs champs :

 
Sélectionnez
VB.Titre := 'Visual Basic 6, Le guide du programmeur';
VB.Auteur := 'Frantz';
VB.AnneePub := 2000;
Gaston.Titre := 'Gaston Lagaffe - Des Gaffes et des Dégâts';
Gaston.Auteur := 'Franquin';
Gaston.AnneePub := 1975;

Après les instructions suivantes :

 
Sélectionnez
AssignFile(f,'Bibliotheque.dat');
rewrite(f);
write(f,Gaston);
write(f,VB);

le fichier Bibliotheque.dat contiendra deux enregistrements de type Livre. Plus précisément, le premier enregistrement contiendra le livre Gaston et le deuxième, le livre VB.

Si, après cela, on fait encore une fois

 
Sélectionnez
write(f,Gaston);

le fichier contiendra trois enregistrements (Gaston, VB, Gaston).

Si on écrit un enregistrement juste après l'ouverture d'un fichier existant (donc avec un reset), cette écriture se fera dans le premier enregistrement du fichier. Par exemple, après l'exécution du code suivant :

 
Sélectionnez
AssignFile(f,'Bibliotheque.dat');
reset(f);
write(f, VB);

le fichier contiendra (VB, VB, Gaston).

Lecture séquentielle

La lecture d'un enregistrement à la suite du dernier enregistrement lu ou écrit se fait par la procédure read. Plus précisément, pour affecter la valeur d'un enregistrement à une variable v, on écrira read(f,v). Cela suppose bien entendu que la variable est du même type que les enregistrements du fichier.

Si le fichier vient d'être ouvert, l'enregistrement lu sera le premier.

Reprenons la suite de l'exemple précédent. Notre fichier Bibliotheque.dat contient à présent trois enregistrements de type Livre (VB, VB, Gaston).

Pour les récupérer, déclarons trois variables de type Livre :

 
Sélectionnez
var Livre1, Livre2, Livre3 : Livre;

Après les instructions suivantes :

 
Sélectionnez
AssignFile(f,'Bibliotheque.dat');
reset(f);
read(f,Livre1);
read(f,Livre2);
read(f,Livre3);

les structures Livre1 et Livre2 contiendront le livre VB et Livre3 contiendra le livre Gaston.

Lecture jusqu'en fin de fichier

De manière générale, on ne connaît pas le nombre d'enregistrements contenus dans un fichier structuré. On utilise alors la fonction eof pour savoir si on est arrivé à la fin du fichier. Voici comment lire séquentiellement un fichier structuré afin d'effectuer un traitement sur chacun de ses enregistrements :

 
Sélectionnez
var f : file of type;
    x : type;
AssignFile(f,'Bibliotheque.dat');
reset(f);
while not eof(f) do
begin
  read(f,x);
  // Traitement de l'enregistrement x
end;

Exercices

Téléchargez les exercices sur le site de l'auteur :

Pour obtenir les corrigés, le téléchargement n'est possible que via un login et un mot de passe, que vous pouvez obtenir en envoyant un mail à l'adresse suivante :

Image non disponible

en précisant un peu qui vous êtes et les raisons pour lesquelles ce cours vous intéresse.


précédentsommaire

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2014 Eric Thirion. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.