Les données manipulées par un programme résident en mémoire, elles sont perdues à la fin du programme ou lors de l'extinction de l'ordinateur. Pour être en mesure de les retrouver il faut les sauver sur un disque dur ou une disquette. Cette opération s'effectue par l'intermédiaire du système de fichiers fournis par le DOS. Pour celui-ci un fichier est caractérisé par un nom qui contient éventuellement un chemin d'accès à travers les lecteurs valides et les répertoires. Turbo Pascal fournit un certain nombre de fonctions et procédures permettant de manipuler les fichiers.
Pour Turbo Pascal, toute opération sur un fichier se fait par l'intermédiaire d'une variable de type File.
Avant d'utiliser une telle variable il est nécessaire de l'initialiser en l'associant à un fichier DOS. Cette opération se réalise par l'intermédiaire de la procédure Assign.
Syntaxe :
Assign(Var FichierPascal:File; NomFichierDos:String);
FichierPascal est la variable de type File associée au fichier DOS nommé NomFichierDos.
Exemple : pour utiliser le fichier monfic.dat contenu dans le répertoire \datas du lecteur c: on l'associera au fichier pascal f en écrivant
Assign(f,'c:\datas\monfic.dat');
Avant de pouvoir effectuer des opérations de lecture ou d'écriture sur un fichier il est nécessaire de l'ouvrir. Cela peut se réaliser de 2 façons :
Lorsqu'on a terminé les opérations de lecture et d'écriture sur le fichier il faut le fermer. Un programme se doit de fermer tous les fichiers qu'il a ouverts.
La fermeture d'un fichier s'effectue par l'intermédiaire de la procédure Close(Var f:File).
Le fichier associé à f est fermé. Il n'est plus possible d'effectuer des opérations de lecture et d'écriture à moins de le rouvrir avec Reset.
Les opérations de manipulation de fichiers sont sujettes à de nombreuses erreurs indépendantes du programme. Par exemple, tentative d'ouverture avec Reset d'un fichier qui n'existe pas, ou tentative de création avec Rewrite d'un fichier sur un disque qui n'existe pas, etc...
Lorsqu'une erreur survient, Turbo Pascal termine en général le programme en cours de façon brutale.
Pour les procédures concernant les fichiers il existe cependant un moyen d'éviter cette fin prématurée. Il s'agit de la directive de compilation {$I-}. Après cette directive, les erreurs dues aux fichiers ne provoquent plus un arrêt du programme. La directive {$I+} rétablit la situation normale. Le programme ainsi protégé d'une fin brutale doit cependant être en mesure de reconnaître si les opérations qu'il a demandées ont pu être effectuées correctement. C'est la fonction IOResult qui joue ce rôle. Elle renvoie un code sous forme d'entier de type Integer qui indique l'erreur survenue lors de la dernière opération effectuée sur un fichier. Le code 0 indique une absence d'erreur. Tout autre code indique une erreur.
Par exemple, pour ouvrir le fichier c:\datas\monfic.dat, on procèdera ainsi :
Assign(f,'c:\datas\monfic.dat'); { associer f à un fichier DOS } {$I-} { protection erreur } reset(f,1); { ouverture } {$I+} { fin protection erreur } if IOResult<>0 then { test erreur } begin { ici traiter l'erreur de façon appropriée } end;
A chaque fichier est associée une position courante (entier de type LongInt) qui indique où les opérations de lecture et d'écriture vont être effectuées. Au départ la position courante est 0. Chaque opération de lecture ou d'écriture d'un bloc élémentaire (dont la taille est déterminée à l'ouverture) augmente la position courante d'une unité. Turbo Pascal fournit une procédure et une fonction gérant la position courante dans un fichier.
La lecture dans un fichier se fait avec la procédure
BlockRead(var f:File; Var Ident; NombreALire : Word[; Var NombreLus:Word]);
f est le fichier visé; Ident est le nom d'une variable de type quelconque qui recevra les informations contenues dans le fichier; NombreALire est le nombre de bloc élémentaires à lire.
Le paramètre facultatif NombreLus permet de récupérer le nombre de blocs effectivement lus.
Evidemment, la lecture se fait à la position courante du fichier qui est ensuite augmentée de NombreALire.
L'écriture dans un fichier se fait avec la procédure
BlockWrite(var f:File; Var Ident; NombreAEcrire : Word[; Var NombreEcrits:Word]);
f est le fichier visé; Ident est le nom d'une variable de type quelconque qui sera écrite dans le fichier; NombreAEcrire est le nombre de bloc élémentaires à écrire.
Le paramètre facultatif NombreEcrits permet de récupérer le nombre de blocs effectivement écrits.
Evidemment, l'écriture se fait à la position courante du fichier qui est ensuite augmentée de NombreAEcrire.
Turbo Pascal propose aussi deux autres fonctions utiles dans ce contexte.
Les fichiers sans type définis précédemment sont suffisamment généraux pour permettre de traiter tout fichier, quelle que soit sa structure. Cette grande généralité est le fruit d'une grande abstraction et entraine donc une certaine complexité. La notion de fichier typé permet de simplifier les opérations de lecture et écriture dans un fichier, mais en réduisant les possibilités. Un fichier typé devra contenir une suite d'éléments qui sont tous de même type.
Le type associé à un fichier typé est déclaré par
NomTypeFichier=file of IdType;
NomTypeFichier est le nom du type créé; IdType est le type des éléments contenus dans le fichier.
file et of sont des mots de Turbo Pascal.
Par exemple, FicEntier = file of Integer; sera la déclaration d'un type de fichiers contenant des entiers de type Integer.
Les procédures d'ouverture et de fermeture sont les mêmes que pour les fichiers sans type (reset, rewrite et close). Pour l'ouverture, il n'est plus nécessaire de préciser la taille des blocs élémentaires puisque c'est le type des données déjà déclaré qui le détermine. Les procédures et fonctions concernant la position courante (seek et filepos) sont toujours valables. De même on pourra utiliser les fonctions EOF et FileSize.
La procédure Read(Var f:File; Var V) permet de lire dans V la donnée située à la position courante de lecture.
La procédure Write(Var f:File; Var V) permet d'écrire V à la position courante dans le fichier.
Par exemple, si f est un fichier d'entiers de type Integer, pour lire le nième entier du fichier on écrira :
seek(f,n); read(f,i);
le nième entier du fichier est transféré dans la variable i de type Integer.
Pour écrire le contenu de i comme nième entier du fichier, on écrira :
seek(f,n); write(f,i);
Notes :
Les fichiers contenant du texte ont une structure particulière qui ne peut pas être ramenée à un fichier typé.
En effet ils sont organisés en lignes séparées par les caractères #13#10. Ces lignes n'ont pas toutes la même longueur d'où l'impossibilité d'utiliser un type à moins de perdre beaucoup de mémoire. Turbo Pascal propose un type particulier pour faciliter la gestion de ces fichiers.
Ce type permet d'utiliser les fichiers contenant du texte. L'association à un fichier Dos, l'ouverture et la fermeture se font comme pour les fichiers sans type. Lors de l'ouverture, il n'y a pas de taille à donner pour les blocs élémentaires. Les fonctions gérant la position courante ne sont plus utilisables avec ce type de fichier, l'accès se fera donc de façon séquentielle, du début vers la fin sans possibilité de retour en arrière. Par contre de nouvelles procédures et fonctions permettront de gérer la notion de ligne.
La procédure Append(var f:Text) ouvre le fichier en fixant la position courante à la fin du fichier. On peut ainsi ajouter des lignes de texte.
La procédure Readln(var f:Text; Var S) lit la ligne courante dans la chaîne S.
La procédure Writeln(var f:Text; Var S) écrit la chaîne S à la position courante et place les caractères #13#10.
Notes :
Le DOS organise les fichiers d'un lecteur en répertoires. L'unité System fournit des procédures et fonctions permettant de réaliser certaines opérations globales sur les fichiers et les répertoires. Les opérations concernant les fichiers doivent être effectuées sur des fichiers fermés.
La procédure ERASE(f:File) efface le fichier f du disque.
La procédure RENAME(f:File;NouveauNom:String) change le nom du fichier f en NouveauNom.
Remarque : si NouveauNom contient un chemin d'accès sur le même lecteur cette procédure correspond à un déplacement du fichier d'un répertoire à l'autre.
La procédure CHDIR(NouveauRepertoire:String) permet de changer de répertoire courant.
La procédure MKDIR(NouveauRepertoire:String) permet de créer un nouveau répertoire.
La procédure RMDIR(Repertoire:String) détruit un sous-répertoire si celui-ci est vide.
La procédure GETDIR(Lecteur:Byte;Chemin:String) renvoie le répertoire courant dans la variable chaîne Chemin; Lecteur est un entier pour lequel : 0 désigne le lecteur courant; 1 désigne le lecteur A:; 2 désigne le lecteur B:; etc...
L'unité DOS fournit d'autres procédures et fonctions de gestion des fichiers et des répertoires comme :