Vous êtes sur la page 1sur 35

Chapitre 5 - Les fichiers en Turbo Pascal

1 Intrt des fichiers


Les entres-sorties, c'est--dire la communication d'informations entre la mmoire d'un ordinateur et ses priphriques ( units de disques, drouleurs de bandes, imprimantes, clavier, cran, etc. ) sont modlises de faon abstraite l'aide de la notion de fichier. Un fichier peut tre considr comme une suite ventuellement vide de composants de mme type dpose sur un support quelconque hors mmoire. C'est le seul moyen offert aux programmes pour communiquer avec le monde extrieur pendant leur excution. Tout programme manipule l'information travers des variables qui rsident dans la mmoire centrale de lordinateur. Linformation nexiste donc que la dure de lexcution du dit programme. Les fichiers sont donc aussi le seul moyen : - de sauvegarder l'information entre plusieurs excutions, - de faire communiquer entre eux plusieurs programmes, quils soient sur une mme machine ou des machines diffrentes, - de transmettre des donnes entre plusieurs machines. Les modes de reprsentations physiques des fichiers varient normment d'un ordinateur l'autre. De plus les fichiers sont du domaine du systme d'exploitation et chaque langage met donc en oeuvre une gestion de fichier adapte au systme sous lequel il est install, ce qui posera un grave problme de portabilit des programmes dune machine une autre. Le seul type de fichier qui soit presque toujours transfrable sans trop de difficult entre deux matriels est le fichier squentiel de caractres frquemment nomm fichier texte. Il est donc difficile d'intgrer la notion de fichier dans un langage de programmation sans courir le risque de choisir un concept trop li l'architecture d'un ordinateur ou d'une famille d'ordinateurs particuliers.

2 Les formats de fichiers


En mmoire centrale, linformation est code en binaire. Outre le fait que lunit centrale ralise tous les calculs avec des circuits lectroniques fonctionnant en logique binaire, lintrt principal de ce codage est que la taille de la zone mmoire ncessaire stocker toutes les valeurs possibles dune variable est fixe. Cette taille est dtermine par le compilateur lors de la dclaration de type de cette variable. Par exemple un entier occupe 2 cases mmoire ( 2 octets ou 16 bits sur un micro-ordinateur ) quelle que soit sa valeur, qui est limite 32767 ; en effet avec 16 bits, on a 216 combinaisons soit 65536 valeurs possibles. Par convention lensemble des Integer est centr sur zro , do un domaine de dfinition de -32768 32767. De la mme faon, une variable de type Word est aussi code sur 16 bits, mais le domaine de dfinition ninclut que des valeurs positives ou nulles soit de 0 65535. Il est important de se souvenir que le codage utilis dpend du matriel ( micro-ordinateur, mini-ordinateur... ) et du langage utilis. Si les informations taient reprsentes en mmoire en clair, par exemple une srie de chiffres dcimaux, la place occupe par une variable serait bien suprieure ; il faudrait probablement rserver 5 cases mmoire pour un entier ( une case par chiffre ) sans compter le signe. De plus la taille effectivement occupe dans la zone rserve dpend de la valeur de la variable. La valeur 1 occuperait une seule case sur les cinq et la valeur 32000 occuperait les cinq cases. Il faudrait donc ajouter une information supplmentaire sur le nombre de cases effectivement occupes dans la zone rserve.
Les fichiers - 1

Lors de lcriture dune variable dans un fichier, ou de sa relecture ultrieure, il convient donc de prciser si lon dsire ou non une conversion entre le format binaire interne la machine et le format usuel utilis par les humains pour reprsenter linformation. On distingue donc deux types de fichiers : binaires et textes. Chacun de ces deux types de fichiers prsente des avantages et des inconvnients qui font que ni lun ni lautre ne peut tre abandonn. - les fichiers binaires, o linformation est dpose par une simple recopie de la zone mmoire associe la variable. A la relecture, le contenu de la zone mmoire est directement relu depuis le disque. Ces fichiers sont souvent nomms fichiers accs direct car le temps d'accs chaque composante est sensiblement constant, ce qui n'est absolument pas le cas dans les fichiers textes. Un autre avantage majeur de ces fichiers est la possibilit de lire et d'crire en mme temps sur le mme priphrique, ce qui simplifiera beaucoup les oprations de modifications des informations. Cette extension est trs simplement obtenue sachant que le fichier est une srie de composantes de mme type et donc de mme taille, ce qui permet au langage de calculer la position physique sur le support d'une composante quelconque partir de son numro d'ordre et de sa taille. Un fichier binaire est donc une extension de la notion de tableau une dimension, extensible par une extrmit. Le seul moyen d'obtenir ce rsultat est de communiquer avec le support en format binaire, cest--dire comme une copie exacte du contenu de la mmoire pour la variable changer avec ce support. Une consquence quelle fois gnante est qu'un tel fichier ne peut contenir que des composantes de mme type et ne pourra tre trait qu'une composante la fois. Le fait que les langages n'inscrivent pas au dbut dun fichier la nature et la taille des composantes, conduit au problme qu'il n'est gnralement pas possible de faire relire un langage un fichier binaire cr par un autre langage, ni mme par le mme langage si l'on ne connat pas la nature ( le type ) des composantes du fichier. Ces fichiers sont donc parfaitement adapts une gestion transactionnelle de l'information, o l'on ralise trs frquemment des mises jour. Il importera ensuite de convertir ces fichiers en format texte si l'on dsire changer leur contenu avec d'autres programmes ou l'archiver. - les fichiers textes, o linformation est convertie du format interne en format lisible par un humain lors de lcriture. A la relecture, lopration de codage en binaire sera effectue pour convertir de nouveau la srie de caractres qui reprsentent la valeur vers le format interne la machine. Un fichier texte est un modle pour tout priphrique d'ordinateur qui est toujours un support sur lequel les informations ne peuvent tre lues ou crites que les unes la suite des autres en commenant par le dbut et sans retour arrire possible : bandes magntiques, imprimantes ou plus anciennement lecteurs-perforateurs de cartes perfores ou de rubans. A partir du moment o l'information est dpose en clair dans un fichier texte, la taille de chaque composante dpend de sa valeur. Il est tout fait possible de dposer des informations de type diffrent dans un tel fichier, la condition bien sur de respecter une certaine rgularit afin de pouvoir relire par une boucle. De plus le programmeur a lentire libert d'organiser son fichier comme il le dsire ; une ou plusieurs informations par ligne, avec ou sans sparateurs entre chacune ( espace, tabulations, virgule... ). Il est donc impossible de se positionner directement sur une information puisque l'on ne peut pas calculer l'endroit o elle commence, puisque cette position dpend des valeurs des composantes qui la prcdent. Il faut donc chaque fois parcourir le fichier depuis le dbut jusqu' ce que l'on ait lu cette information. Il est aussi impossible de reculer, c'est--dire de se remettre au dbut de l'information aprs l'avoir lue. En effet, les procdures de lecture dans un fichier ( Read ou Readln ) ne retournent pas le nombre de caractres qu'elles viennent de lire. On ne sait donc jamais de combien de caractres il faudrait reculer. Enfin, il est impossible de modifier une valeur au milieu d'un fichier texte car la place ncessaire la nouvelle valeur sera trs probablement
Les fichiers -

diffrente de celle de l'ancienne. Donc, soit on crasera le dbut de la valeur qui suit, soit on laissera entre les deux des caractres parasites. Reconnaissant ce fait, la plupart des langages informatiques, dont Pascal, interdisent d'ouvrir un fichier texte la fois en lecture, pour en consulter le contenu, et en criture pour en modifier une partie. Donc toute intervention sur un fichier texte ncessitera de le recopier intgralement dans un second, en intervenant au vol sur la valeur vise ; soit en ne la recopiant pas, ce qui a pour effet de la supprimer, soit en recopiant sa nouvelle valeur pour la changer. Ces considrations pourraient inciter penser que les fichiers textes devraient tre abandonns au plus vite. C'est malheureusement totalement faux, puisque le format texte est bien le seul qui permette des changes entre langages, programmes ou machines. Sans parler de l'archivage de l'information : il faut que les archives puissent tre reconsultes dans de nombreuses annes, quand les PC et Turbo Pascal auront disparu depuis longtemps.

3 Organisation des informations sur les mmoires de masse


Bien que les primitives daccs aux fichiers offertes par Pascal soient relativement de haut niveau, et masquent de ce fait beaucoup de dtails de mise en oeuvre relle, leur comportement est fortement influenc par la faon dont linformation est effectivement dpose sur le disque. Il nest donc pas inutile davoir quelques ides sur lorganisation physique et logique de linformation sur les supports. On nomme un priphrique, tout organe extrieur lunit centrale de lordinateur capable dchanger de linformation avec elle. On distingue les mmoires de masse et les priphriques dentre-sortie. Les mmoires de masse sont des organes priphriques sur lesquels il est possible de stocker des informations de manire permanente. Ces supports sont caractriss par leur capacit de stockage et le temps moyen pour accder une information. Suivant les cas, ces supports peuvent tre des bandes magntiques, des disquettes, des disques dits durs, soit magntiques, soit magntooptiques ou optiques. Les priphriques dentre-sortie sont des organes de communication entre lunit centrale et le monde extrieur. Certains sont en lecture seule, comme le clavier, dautres criture seule comme lcran ou une imprimante ou mixtes comme un modem. La communication se fait gnralement en mode squentiel, par change de caractres. Linformation y est stocke de faon semi permanente. En ce sens, lcran et limprimante peuvent tre considres comme des sortes de mmoire de masse. Il nest donc pas surprenant que les primitives utilises pour la gestion des fichiers ( et en particulier des fichiers textes ) soient trs similaires celles qui vous connaissez dj pour les classiques entres-sorties lcran ou au clavier.

3.1 Organisation physique


3.1.1 les bandes magntiques. Le stockage sur bandes magntiques se fait la suite, c'est dire que pour accder une information, il faut drouler la bande jusqu' l'endroit o se trouve la dite information. Ce support est de grande capacit ( de 300 1000 M octets ) mais lent. Il tend tre remplac par d'autres supports comme les disques optiques. L'utilisation de ce support est rserve uniquement l'archivage. 3.1.2 les disques. La surface du disque est recouverte d'oxyde qui peut recevoir ou fournir des informations. Le disque est divis en pistes ( cercles concentriques ) et en secteurs ( portions de piste ). Chaque secteur contient un certain nombre d'octets ( de 128 1024 octets ou plus suivant les technologies ).
Les fichiers - 3

Pour se positionner un endroit donn du disque ( repr par son numro de piste et son numro de secteur ), le bras place la tte de lecture/criture sur la piste par un mouvement horizontal, la rotation du disque permet au bout d'un certain temps de se trouver sur le secteur cherch. Le temps de positionnement du bras est long ( par rapport au temps de lecture/criture des informations ), c'est pourquoi les transferts ( en lecture ou en criture ) se font par au moins un secteur. Un secteur est l'unit minimale pour un fichier. Mme si un fichier a une taille infrieure celle d'un secteur, la totalit de ce dernier lui sera rserv. Afin d'optimiser les accs disque, le systme d'exploitation attend d'avoir suffisamment de secteurs en attente d'criture pour mettre en route la mcanique du disque. Il utilise des tampons mmoire qu'il purge sa convenance vers le disque. Ceci ne doit jamais tre oubli. Tant que l'on n'a pas referm un fichier, rien ne prouve que les dernires informations ont effectivement t dposes sur le disque. Donc si vous oubliez de refermer un fichier, ou si votre programme s'interrompt inopinment, le fichier associ risque fort d'tre endommag ou incomplet. Et vous ne vous en apercevrez qu' la prochaine excution, en tentant de le relire.

3.2 Organisation logique


Les grandes capacits d'informations qui peuvent tre stockes sur les disques ncessitent une organisation de tous ces fichiers. Chaque priphrique contiendra des fichiers ou des rpertoires ( un rpertoire sera un espace dot d'un nom et contenant soit des fichiers, soit d'autres rpertoires ). Pour localiser un fichier sur un priphrique, il faudra donner la suite des noms de rpertoires qu'il faut traverser depuis la racine jusqu'au rpertoire qui le contient. Cette localisation s'appelle le chemin ( path ). Les noms des priphriques, les noms de rpertoires et de fichiers obissent aux conventions du systme d'exploitation utilis. Pour manipuler un fichier, il faudra donc imprativement : - dclarer une variable particulire de type fichier sur laquelle se feront toutes les oprations, - associer cette variable un nom physique, selon les conventions en vigueur pour le systme d'exploitation.

4 Le type fichier en Pascal


Il y a trois classes de types fichier en Pascal : typ, non typ et texte. Les fichiers typs ou non sont les fichiers binaires. Le nombre de composants d'un fichier ( la taille du fichier ) n'est pas prdterminer dans la dclaration du fichier. Un fichier est donc seulement limit par la place disponible sur le support. Pascal garde la trace des accs au fichier grce un pointeur de fichier. Chaque fois qu'un composant est crit ou lu dans un fichier, le pointeur de fichier est automatiquement avanc sur le composant suivant.

Les fichiers -

4.1 Dclarations des types fichiers


type fichier :

type file

of

type

type text
Un fichier binaire ( typ ) est dfini par le mot rserv File Of suivi par le type des composants de ce fichier. Le type des composants d'un fichier peut tre quelconque, sauf un type fichier. La dclaration suivante cre une variable interne F qui sera ensuite utilise pour accder un fichier externe qui devra contenir une squence de nombres entiers cods en binaire : Var F : File Of Integer ; et celles-ci mettent en place des fichiers binaires contenant des enregistrements de type Tproduit et des chanes de 80 caractres. Type tNomDeProduit = String [ 80 ] ; tProduit = Record Nom : tNomDeProduit ; CodeProduit : Integer ; Quantite : Real ; StockMini : Real ; CodeFourni : Integer End ; Var FicNoms : FicProduits : ou directement FicNoms: File Of tNomDeProduit ; File Of tProduit ; File Of String [ 80 ] ;

Un fichier texte se dclare avec le mot rserv Text : Var OutFile : Text ; Le fichier externe qui sera associ une variable de type Text doit contenir de linformation en clair comme une squence de caractres groups en lignes ; chaque ligne est termine par un indicateur de fin de ligne compose du caractre de code 13 ( CR ou retour chariot ) suivi du caractre de code 10 ( LF ou saut de ligne ). Le fichier est lui-mme termin par une marque de fin de fichier ( EOT de code 26 ). Le code de fin de ligne est mis la discrtion du programmeur par un ordre Writeln. Quant au code de fin de fichier, il est dpos lors de lappel la procdure Close.
Les fichiers - 5

Les fichiers sans type se dclarent avec le simple mot File. Ce sont des canaux d'entre-sortie de bas niveau utiliss en premier lieu pour les accs directs tout fichier disque, quel que soit son type et sa structure. Ils utilisent par dfaut une taille d'enregistrement de 128 octets. Un fichier sans type est compatible avec tout autre fichier. L'emploi d'un fichier sans type sera donc prfr pour renommer ou effacer un fichier, ou pour toute autre opration n'impliquant pas d'entres-sorties. Il est possible de lire ou dcrire dans de tels fichiers, mais il faudra chaque fois prciser le nombre dinformations que lon dsire puisque quen labsence du type des composantes, Pascal ne pourra pas le calculer lui-mme. Var DataFile : File ; De faon interne au Pascal, une variable fichier est dcrite par un enregistrement de type FileRec ( export par lunit SYSTEM ). Les variables de type fichier ne peuvent pas apparatre dans les affectations ou les expressions. De mme un objet fichier ne peut tre pass en paramtre une procdure que par rfrence : un passage par valeur impliquerait une recopie du fichier externe associ.

4.2 Utilisation des fichiers


4.2.1 Association entre une variable fichier et un fichier externe Pour pouvoir tre utilise, une variable fichier ( situe en mmoire ) doit imprativement tre initialise en lassociant un fichier externe grce un appel la procdure Assign ( Var F : File ; Nom : String ) ; Nom est une expression chane rsultant en tout nom lgal de fichier pour le systme d'exploitation en vigueur. Le nom de fichier est affect la variable fichier interne F et toutes les oprations suivantes sur F affecteront le fichier externe dont le nom a t spcifi dans l'expression Nom. Assign ne doit jamais tre utilis une seconde fois sur un fichier en cours d'utilisation. Il convient dans ce cas de refermer le fichier avant de raliser de nouveau lassociation. Lexpression chane peut tre une constante ou une variable convenablement initialise ou le rsultat de toute opration valide sur des chanes de caractres comme : Var T : Text ; F : File Of Real ; Assign ( T , 'c:\tp\travail\essai.txt' ) Assign ( F , 'essai.dat' ) ; Assign ( T , 'm:\essai.txt' ) ; Const NomFic = c:\tp\travail\donnees.txt ; ..... Assign ( T , NomFic ) ; Var NomFic : String ; .... Write ( sur quel fichier va-t-on travailler ? ) ; Readln ( NomFic ) ; Assign ( F , NomFic ) ;
Les fichiers -

Const Repertoire = m: ; Fichier = essai.txt ; .... Assign ( T , Repertoire + \ + Fichier ) ; 4.2.2 Ouverture dun fichier On doit ensuite procder louverture du fichier, cest--dire la cration par le systme dexploitation dune zone de transfert en mmoire, le tampon dchange. Selon le mode douverture choisi ( lecture, criture ou les deux ) lexploitation du tampon sera diffrente. Les accs disque effectifs se font via ce tampon la discrtion du systme dexploitation. Il ne faut jamais prjuger quune information est immdiatement dpose sur le disque aussitt aprs une opration dcriture, ni quelle vient du disque sur une opration de lecture. Cette considration est particulirement importante lors des accs un fichier partag sur un serveur. Ce nest qu la fermeture du fichier que le systme purgera le tampon et rcuprera la mmoire utilise. Une erreur lexcution se produit si vous essayez de transfrer un fichier qui a t ouvert en lecture une procdure oriente en sortie ( Write ou Writeln ). De la mme manire, c'est une erreur que de transfrer un fichier qui a t ouvert en criture une procdure oriente en entre ( Read ou Readln ). Les procdures utiliser pour louverture dun fichier se nomment Reset, Rewrite et Append. Elles ont un comportement diffrent selon le type du fichier ( binaire, texte ou sans type ). Nous les dtaillerons dans chaque cas dans les sections suivantes. 4.2.3 Fermeture dun fichier En fin dutilisation un fichier doit tre ferm pour une purge ventuelle du tampon interne ; Le rpertoire du disque est mis jour pour tenir compte des dernires modifications apportes au fichier. Ce nest quaprs cette opration que lon peut tre assur que toutes les oprations dcriture sont physiquement ralises sur le disque. Loubli de refermer un fichier, ou un arrt imprvu du programme avant cette fermeture risque de produire un fichier externe incomplet quil sera impossible de relire convenablement lors dune prochaine excution du programme. Remarquez qu'il est ncessaire de fermer un fichier mme si vous n'avez fait que des oprations de lecture. Sinon vous auriez rapidement trop de fichiers ouverts la fois ( 20 tampons peuvent tre ouvert simultanment sous MsDos ). En Turbo Pascal, il se produit une erreur lexcution si l'on referme un fichier qui n'avait pas t ouvert. 4.3 Gestion des erreurs Tous les appels de procdures et de fonctions d'entres-sorties font automatiquement l'objet d'un contrle d'erreur. Si une erreur survient, le programme se termine en affichant un message d'erreur l'excution ( Run-time error ). Ce contrle automatique peut tre dsactiv et ractiv en utilisant les directives de compilation {$I-} et {$I+}. Lorsque le contrle d'entres-sorties est dsactiv, c'est--dire lorsqu'une srie dinstructions est prcde de {$I-}, une erreur d'entre-sortie ne cause pas l'arrt du programme, mais suspend toute autre opration d'entre-sortie jusqu' ce que la fonction standard IOresult soit appele. Cette particularit permet de tenter sans risque plusieurs oprations disques en squence et de ne tester quune fois la fin si tout s'est bien pass. Lorsque ceci est fait, la condition d'erreur est remise zro et les oprations d'entre-sortie sont effectues de nouveau. Il est alors de la responsabilit du programmeur de corriger l'erreur d'entre-sortie. La valeur zro retourne par IOresult indique que tout c'est bien pass. Tout autre valeur signifie qu'une erreur est survenue pendant la dernire opration d'entre-sortie. La
Les fichiers - 7

signification des divers codes d'erreur est disponible dans laide en ligne du Turbo Pascal ( menu Help|Error Messages ). A titre dexemple la squence suivante ne provoque pas larrt du programme si vous tapez au clavier des caractres non numriques sur le Readln vers la variable entire N : Var N : Integer ; {$I-} Repeat Readln ( N ) Until Ioresult = 0 ; {$I+} Dans les sections suivantes, nous utiliserons de nombreuses fois cette technique pour fiabiliser des parties critiques de programmes. 4.4 Interventions sur le nom physique dun fichier Les deux oprations suivantes permettent dintervenir directement sur le fichier externe associ une variable fichier interne. Procedure Erase ( Var T : File ) ; Le fichier disque associ T est effac. Si ce fichier est en cours dutilisation, il est impratif de le fermer avant de l'effacer. Le fichier physique correspondant doit exister sur le disque. Une construction standard est la suivante : Var F : File ; {$I-} Assign ( F , c:\tp\travail\essai.dat ) ; Erase ( F ) ; If IOresult <> 0 Then Writeln ( impossible deffacer le fichier ) ; {$I+} Procedure Rename ( Var T : File ; NouveauNom : String ) ; Le fichier disque associ T est renomm en NouveauNom. Le rpertoire du disque est mis jour pour montrer le nouveau nom du fichier et les oprations ultrieures sur T auront lieu sur le fichier avec ce nouveau nom. Rename ne doit jamais tre utilis sur un fichier ouvert. Remarque : Le programmeur doit s'assurer que le fichier dnot par NouveauNom n'existe pas dj. Une construction standard est la suivante : Assign ( F , NouveauNom ) ; {$I-} Erase ( F ) ; If IOresult <> 0 Then ; { si erreur ne rien faire } Assign ( F , AncienNom ) ; Rename ( F , NouveauNom ) ; If IOresult <> 0 Then Writeln ( nouveau nom invalide ou ancien nom introuvable ) ; {$I+}

Les fichiers -

5 Les fichiers textes en Turbo Pascal 5.1 Ouverture et fermeture de fichiers textes
Avant de pouvoir tre exploite, une variable fichier interne doit avoir t associe un fichier externe avec Assign, puis le fichier doit tre ouvert par lune des trois mthodes suivantes : Procedure Rewrite ( Var T : Text ) ; Un nouveau fichier disque dont le nom a t pralablement assign la variable T est cr et prpar pour le traitement en criture seule. Le contenu de tout fichier prexistant avec le mme nom est dtruit. Un fichier disque cr par Rewrite ne contient aucune information. Par exemple les instructions suivantes crent un fichier de taille zro sur le disque M: Vous pouvez vrifier ce fait en lisant le catalogue de M: Assign ( T , m:vide.txt ) ; Rewrite ( T ) ; Close ( T ) ; Procedure Reset ( Var T : Text ) ; Le fichier disque dont le nom a t pralablement assign la variable T est prpar pour traitement en lecture seule. Le pointeur du fichier est positionn au dbut de ce fichier. Le nom du fichier externe correspondant doit exister sur le disque, sinon il se produira une erreur fatale d'entre/sortie. La construction suivante permet dviter ce problme. Assign ( F , SonNom ) ; {$I-} Reset ( F ) ; If IOresult <> 0 Then Begin Rewrite ( F ) ; Reset ( F ) ; End ; {$I+}

{ cration } { puis rouverture en lecture }

Procedure Append ( Var T : Text ) ; Ouvre un fichier texte existant en mode ajout, cest--dire en mode criture avec positionnement du pointeur de fichier la suite de la dernire ligne. Append doit tre utilis la place de Rewrite si l'on dsire ajouter une information la fin d'un fichier texte. La construction suivante permet de rsoudre le problme de lappel Append vers un fichier qui nexisterait pas dj sur le disque : {$I-} Append ( T ) ; If IOresult <> 0 Then Rewrite ( T ) ; {$I+}

{ si chec alors cration }

Les fichiers - 9

Procedure Close ( Var T : Text ) ; Close est lunique mthode pour refermer un fichier. La variable interne redevient disponible pour une autre association ou une ouverture du mme fichier externe dans un autre mode. Procedure Flush ( Var T : Text ) ; Flush vide le tampon interne associ au fichier T et assure que ce tampon a t crit sur le disque. Flush permet galement de s'assurer que la prochaine instruction de lecture effectuera rellement une lecture physique depuis le disque. En environnement rseau ou pour des donnes sensibles, il est prudent dappeler rgulirement Flush pour forcer lcriture physique des dernires modifications. Flush ne doit jamais tre utilis sur un fichier ferm et ne referme pas le fichier.

5.2 Fonctions d'tats sur les fichiers textes


Function Eof ( Var T : Text ) : Boolean ; Applique un fichier texte, la fonction Eof retourne Vrai si le pointeur de fichier est positionn sur la marque de fin de fichier ( le caractre de code 26 ). Eof est toujours Vrai sur un fichier ouvert avec Rewrite ou Append. La construction suivante permet un traitement global dun fichier texte ouvert en lecture. Notez notre choix de la boucle TantQue plutt que Rpter Jusqu qui permet dviter un grave problme de lecture impossible si le fichier tait initialement vide : While Not Eof ( T ) Do Begin { instructions de lecture dune information} { instructions de traitement de cette information } End ; Function SeekEof ( Var T : Text ) : Boolean ; Similaire Eof, mais carte les espaces, les tabulations ou les lignes vides avant de tester la marque de fin de fichier. Function Eoln ( Var T : Text ) : Boolean ; Fonction boolenne retournant Vrai si la fin de ligne a t atteinte, c'est--dire si le pointeur de fichier est positionn sur le caractre CR de la squence CR/LF. Si Eof ( T ) est Vrai, alors Eoln ( T ) est galement Vrai. Un exemple classique est le suivant o nous lisons le contenu du fichier ligne ligne. Notez linstruction Readln ( T ) qui permet lorsque Eoln est devenu Vrai de passer la ligne suivante : While Not Eof ( T ) Do Begin While Not Eoln ( T ) Do Begin {instructions de lecture de la ligne courante} End ; Readln ( T ) { passage la ligne suivante} End ;
Les fichiers -

10

Function SeekEoln ( Var T : Text ) : Boolean ; Similaire Eoln, mais carte les espaces et les tabulations avant de faire le test de fin de ligne.

5.3 Entre et sortie de textes


Les fichiers texte utilisent les primitives Read, Readln ou Write, Writeln exactement comme pour les entres-sorties au clavier et l'cran. Les valeurs sont automatiquement converties partir de ou vers leur reprsentation binaire sous forme de suite de caractres. Par exemple, Read ( F, N ), N tant une variable entire, espre trouver la position courante du fichier texte une squence de chiffres reprsentant un nombre entier. Cette instruction lira cette squence, la codera en binaire et la stockera dans la variable N. Tout caractre illgal provoquera une erreur lexcution, moins que ce type derreur ait t dsactiv. Procedure Read ( Var T : Text ; Var V1 , V2 ,. . . , Vn ) ; Read permet l'entre de caractres, chanes, et de donnes numriques. V1, V2,...,Vn sont des variables de type simple ( caractre, chane, entier, ou rel ). Les variables de type boolen, numrs ou structurs ne peuvent tre lues directement et doivent faire lobjet dun transcodage ou dune dcomposition en type simple comme dans les exemples suivants : { lecture dun type numr depuis un fichier texte } Type tJour = ( lundi , mardi , mercredi , jeudi , vendredi , samedi , dimanche , erreur ) ; Var J : tJour ; L : String ; ....... Readln ( T , Ligne ) ; If Ligne = lundi Then J := lundi Else If Ligne = mardi Then J := mardi Else ..... { les autres cas possibles de mercredi dimanche } Else J := erreur ; { en cas dautre chose ! } { lecture dun enregistrement dispos sur trois lignes dun fichier texte } Type tInfo = Record Nom , Prenom : String ; Age : Integer End ; Var Fiche : tInfo ; ... With Fiche Do Begin Readln ( T , Nom ) ; Readln ( T , Prenom ) ; Readln ( T , Age ) End ; Procedure Readln ( Var T : Text ; Var V1 , V2 ,..., Vn ) ; La procdure Readln est identique la procdure Read, except que lorsque la dernire variable a t lue, le reste de la ligne est ignor. Tous les caractres, jusque et y compris la
Les fichiers - 11

prochaine squence CR/LF, sont carts. Aprs une instruction Readln, une opration Read ou Readln lira au dbut de la ligne suivante. Readln peut galement tre appele sans paramtre. Dans ce cas, le reste de la ligne est ignor. Avec une variable de type Char : Read lit un caractre dans le fichier et affecte ce caractre cette variable. Eoln devient Vrai si le caractre suivant est un retour chariot ou un la marque de fin de fichier. Eof devient Vrai si le caractre suivant est une marque de fin de fichier ou une fin de fichier physique. Avec une variable du type String : Read lit autant de caractres que permis par la dclaration de la longueur de la chane, moins que Eoln ou Eof soient rencontrs avant. Tous les caractres prsents sont significatifs, y compris les espaces ou les tabulations. Si un fichier texte contient plusieurs informations de type textuel par ligne, il est donc capital de dimensionner correctement les chanes des caractres qui recevront les valeurs lors de la lecture. Eoln devient Vrai si le caractre suivant est un retour chariot ou la marque de fin de fichier. Eof devient Vrai si le caractre suivant est une marque de fin de fichier ou une fin de fichier physique. Par exemple si un fichier contient les informations suivantes : Un prnom sur les 20 premires colonnes de chaque ligne Un nom sur les 20 colonnes suivantes {0 1 2 3 4 5} {12345678901234567890123456789012345678901234567890}
BERNARD ALAIN MICHEL DUPONT DURAND DUBOIS

Il faudra lire ce fichier en dclarant deux variables Prnom et Nom exactement dimensionnes comme des String [ 20 ] comme suit. Notez lutilisation de la Function Trim, de lunit Chanes qui permet de supprimer les espaces situs la fin du Prnom et du Nom qui ont aussi t lus dans le fichier : Uses Chaines ; Var Nom , Prenom : String [ 20 ] ; ...... While Not Eof ( T ) Do Begin Readln ( T , Prenom , Nom ) ; Prenom := Trim ( Prenom ) ; Nom := Trim ( Nom ) ; Traiter ( Prenom , Nom ) End ; Une autre solution serait de lire le fichier un caractre la fois et de reconstituer les chanes nom et prnom en utilisant le premier espace comme indicateur de sparation entre les deux.

Les fichiers -

12

Uses Chaines ; Var C : Char ; .... While Not Eof ( T ) Do Begin Nom := ; Prenom := ; C := * ; While ( C <> ) Do Begin Read ( T , C ) ; Prenom := Prenom + C End ; While C = Do Read ( T , C ) ; While Not Eoln ( T ) Do Begin Read ( T , C ) ; Nom := Nom + C End ; Nom := Trim ( Nom ) ; Readln ( T ) End ;

{ lecture du prnom }

{ ignorer espaces avant le nom} { lecture du nom }

{ ligne suivante }

Une solution plus simple serait de lire le fichier ligne ligne dans une chane de caractres et de dcomposer ensuite cette ligne en un Prnom et un Nom en recherchant le premier caractre espace. Les fonctions Pos, Copy et Delete sont des oprations standard du Turbo Pascal. ( voir laide en ligne ). Var Ligne : String ; While Not Eof ( T ) Do Begin Readln ( T , Ligne ) ; P := Pos ( , Ligne ) ; Prenom := Copy ( Ligne , 1 , P - 1 ) ; Delete ( Ligne , 1 , P ) ; Nom := Trim ( Ligne ) End ; En conclusion, et si lon a le choix, il est beaucoup plus simple de crer un fichier texte avec une information par ligne, ce qui permettra de le relire ultrieurement par une simple srie de Readln. Avec une variable numrique ( entier ou rel ) : Read attend une chane de caractres se conformant au format d'une constante numrique du type adquat. Tous les espaces, les tabulations, les retours chariots ou les fins de ligne prcdant la chane sont carts. La chane ne doit pas avoir plus de 30 caractres, et elle doit tre suivie par un espace, une tabulation, un retour chariot, ou une marque de fin de fichier.

Les fichiers - 13

Si la chane ne se conforme pas au format attendu, il se produit une erreur d'entre/sortie. Dans le cas contraire, la chane numrique est convertie en une valeur du type appropri qui est affecte la variable. Eoln est Vrai si la chane est suivie dun retour chariot ou dune fin de fichier, et Eof est Vrai si la chane est termine par une fin de fichier. Cas particulier : Si Eoln ou Eof est Vrai au dbut de l'opration Read ( si on lit seulement un retour chariot sur le clavier ), aucune valeur n'est affecte la variable qui reste inchange. Par exemple un fichier qui contiendrait quatre nombres entiers par ligne, spars par des tabulations ( ou des espaces ) comme celui-ci : 1 2 5 6 9 10 ... 3 4 7 8 11 12

devrait tre lu par la squence suivante ( avec A, B, C, D dclares comme des entiers ) : While Not Eof ( T ) Do Begin Readln ( T , A , B , C , D ) ; Traiter ( A , B , C , D ) End ; Procedure Write ( Var T : Text ; Var V1 , V2. . . , Vn ) ; La procdure Write permet la sortie de variables de type simple comme les caractres, chanes, valeurs boolennes, et valeurs numriques. V1, V2 ,..., Vn sont des variables du type simple, suivies ventuellement du signe ':' et d'une expression entire dfinissant la longueur du champ de sortie ( paramtres dcriture ). Le format d'un paramtre d'criture dpend du type de la variable. Dans les descriptions suivantes des diffrents formats et de leurs effets, nous utilisons les symboles suivants : l, m, n reprsentent une expression entire. R reprsente une expression relle. Ch reprsente une expression caractre. S reprsente une expression chane. Write ( T , Ch ) Le caractre Ch est sorti. Write ( T , Ch:n ) Le caractre Ch est sorti, justifi a droite dans un champ de n caractres, c'est-dire que Ch est prcd par n - 1 espaces. Write ( T , S ) La chane S est sortie. Write ( T , S:n ) La chane S est sortie, justifie droite dans un champ de n caractres. S est prcde par n - Length ( S ) espaces. Write ( T , I ) La reprsentation dcimale de la valeur I est sortie. Write ( T , I:n ) La reprsentation dcimale de la valeur de I est sortie, justifie droite dans un champ de n caractres. Write ( T , R ) La reprsentation de la valeur de R est sortie en notation scientifique.
Les fichiers -

14

Write ( T , R:n ) La reprsentation dcimale de la valeur de R est sortie, justifie droite dans un champ de n caractres, en utilisant la notation en virgule flottante. Write ( T , R:n:m ) La reprsentation dcimale de la valeur de R est sortie, justifie droite dans un champ de n caractres, en utilisant la notation en virgule flottante avec m chiffres aprs le point dcimal. Si m est gal zro, il n'y a pas de partie dcimale ni de point sortis. Le nombre est prcd par un nombre d'espaces appropri pour remplir un champ de n caractres. Procedure Writeln ( Var T : Text ; Var V1 , V2 , . . . , Vn ) ; La procdure Writeln est identique la procdure Write, avec l'mission d'une squence CR/LF aprs la dernire valeur. Une instruction Writeln sans paramtres d'criture crit seulement une ligne vide ou termine la ligne en cours.

6 Manipulations simples de fichiers textes


Le programme suivant cre un fichier texte contenant les nombres de 10 20 raison de un par ligne, soit onze lignes. Program CreeFichierDeNombres ; Var T : Text ; I : Integer ; Begin Assign ( T , 'NB10A20.TXT' ) ; Rewrite ( T ) ; { ouverture en criture } For I := 10 To 20 Do Writeln ( T , I ) ; { accs en criture} Close ( T ) { fermeture} End . Puisque le fichier ainsi cr est un texte, vous pouvez le relire avec n'importe quel traitement de texte et ventuellement le modifier. Pour en voir le contenu il suffit de l'ouvrir avec Turbo Pascal, en n'oubliant pas de spcifier l'extension ( TXT ). Vous devriez voir apparatre dans une nouvelle fentre : 10 11 12 ... 20 exercice 6.1 : quel sera l'aspect du fichier NB10A20.TXT si on remplace le Writeln ( T , I ) par Write ( T , I ) ou par Write ( T , I:4 ) ? exercice 6.2 : quel serait l'aspect du fichier NB10A20.TXT si on omettait l'instruction Close ? Nous pouvons aussi le relire par un programme Pascal symtrique, qui ouvre le fichier en lecture, puis relit chaque nombre par des Readln, puisque nous avions dpos un nombre par ligne, et les affiche l'cran :

Les fichiers - 15

Program RelitFichierDeNombres ; Var T : Text ; I , N : Integer ; Begin Assign ( T , 'NB10A20.TXT' ) ; Reset ( T ) ; For I := 1 To 11 Do Begin Readln ( T , N ) ; Writeln ( N ) End ; Close ( T ) ; Readln End .

{ ouverture en lecture seule }

{ lecture d'un nombre } { et affichage } { fermeture } { pour avoir le temps de voir le rsultat ! }

exercice 6.3 : le programme suivant n'affiche pas correctement les 11 nombres. Pourquoi ? Assign ( T , 'NB10A20.TXT' ) ; Reset ( T ) ; For I := 1 To 11 Do Begin Readln ( F , I ) ; Writeln ( I ) End ; Close ( T ) ; Le programme prcdent risque de poser problme si le fichier NB10A20.TXT ne contient pas exactement 11 nombres. S'il en a moins, il sarrtera avec une erreur fatale d'entre-sortie ( lecture au-del de la fin d'un fichier ) et s'il y en plus, il n'affichera que les onze premiers. Nous lui prfrerons donc la version suivante qui affiche l'ensemble du fichier, quelle que soit sa taille grce l'utilisation de la fonction Eof : Program RelitFichierDeNombres ; Var T : Text ; I : Integer ; Begin Assign ( T , 'NB10A20.TXT' ) ; Reset ( T ) ; While Not Eof ( T ) Do Begin Readln ( T , I ) ; Writeln ( I ) End ; Close ( T ) ; Readln End . exercice 6.4 : comment relire le fichier NB10A20.TXT s'il avait t fabriqu avec Write ( T , I ) ou Write ( T , I:4 ) ? Un des gros avantages des fichiers textes est qu'ils peuvent toujours tre considrs comme des fichiers de caractres. Pour les relire il suffit donc d'en extraire l'information un caractre la fois comme le montre l'exemple suivant. Remarquez l'utilisation de Read qui lit exactement la quantit
Les fichiers -

16

d'information spcifie par le type de son paramtre ( ici un caractre ) et non pas de Readln qui chercherait changer de ligne entre chaque caractre du fichier. Program RelitToutFichierTexte ; Var T : Text ; Nom : String ; C : Char ; Begin Write ( 'nom du fichier lire : ' ) ; Readln ( Nom ) ; Assign ( T , Nom ) ; Reset ( T ) ; While Not Eof ( T ) Do Begin Read ( T , C ) ; Write ( C ) End ; Close ( T ) ; Readln End . Si le fichier est organis en lignes, on peut aussi le relire une ligne la fois, par une srie de Readln vers une variable de type chane de caractres. Il importe seulement qu'aucune ligne ne soit plus longue que la taille maximale permise par un type String, soit 256 caractres. Program RelitToutFichierTexteAvecDesLignespasTropLongues ; Var T : Text ; Nom , Ligne : String ; I , N : Integer ; Begin Write ( 'nom du fichier lire : ' ) ; Readln ( Nom ) ; Assign ( T , Nom ) ; Reset ( T ) ; While Not Eof ( T ) Do Begin Readln ( T , Ligne ) ; Writeln ( Ligne ) End ; Close ( T ) ; Readln End . exercice 6.5 : crire un programme qui affiche le nombre de lignes d'un fichier texte, d'abord en admettant que chaque ligne a une longueur infrieure 256 caractres puis en levant cette restriction. exercice 6.6 : crire un programme qui affiche le nombre de mots d'un fichier texte, d'abord en admettant que chaque ligne a une longueur infrieure 256 caractres puis en levant cette restriction. exercice 6.7 : crire un programme qui affiche le nombre de chiffres et de lettres contenu dans un fichier texte.
Les fichiers - 17

exercice 6.8 : crire un programme qui affiche le numro de chacune des 26 lettres de l'alphabet contenu dans un fichier texte. On utilisera une fonction CarMajuscule ( C : Char ) : Char qui convertit en majuscule un caractre si ncessaire et le renvoie inchang sinon. Pour tester ce programme, il vous suffira d'utiliser l'unit Chanes disponible sur le serveur qui exporte cette fonction.

7 Modification du contenu d'un fichier texte


Comme nous l'avons dj signal, un fichier texte ne peut pas tre ouvert simultanment en lecture et en criture. L'appel Reset interdit l'utilisation des primitives de type Write et l'appel Rewrite commence par dtruire le contenu du fichier ! Il est donc impossible de modifier le contenu d'un fichier texte en crivant la nouvelle valeur d'une information par dessus l'ancienne, et encore moins d'y insrer ou d'y supprimer une information. En effet ces oprations ncessitent que l'on lise le contenu du fichier jusqu' l'information voulue, puis que l'on crive cet endroit prcis, et enfin que l'on continue lire la suite du fichier. Toute intervention sur un fichier texte ncessite donc l'utilisation d'un second fichier texte temporaire selon la mthode gnrale suivante : - on ouvre en lecture le fichier originel, - on ouvre en criture le fichier temporaire, ce qui aura pour effet de le crer s'il n'existe pas ou d'en dtruire un contenu prcdent, - on recopie le fichier originel dans le fichier temporaire jusqu' ce que l'on ait atteint l'information vise, - on ralise l'intervention sur le fichier temporaire comme suit : - criture d'une autre valeur en cas de modification, - criture d'une nouvelle information en cas d'ajout, - pas d'action pour une suppression, - ... - on poursuit la recopie du fichier originel vers le fichier temporaire jusqu sa fin. Et ce n'est pas fini ! A la fin de cette opration, le fichier disque qui a le nom utilis par le programme contient toujours l'ancienne version de l'information. C'est le fichier dont le nom est celui choisi pour le fichier temporaire qui contient la bonne version. Il faut donc : - soit recopier le fichier temporaire dans le fichier originel et supprimer le fichier temporaire, - soit changer les noms sur le disque par une utilisation judicieuse des primitives Rename et Erase vues ci-dessus. Si vous avez dj ralis des insertions de morceaux de musique au beau milieu de cassettes audio, cette mthode doit vous tres familire. Il vous faut deux lecteurs de cassettes, un pour lire et l'autre pour enregistrer et la fin vous mettez jour les tiquettes sur les bandes. Afin de simplifier l'criture de ces algorithmes, nous allons utiliser les procdures utilitaires cidessous : procedure OuvreEnLecture ( Var F : Text ; SonNom : String ) ; Ouvre le fichier texte F en lecture, en l'associant au fichier physique SonNom. procedure OuvreEnEcriture ( Var F : Text ; SonNom : String ) ; Ouvre le fichier texte F en criture, en l'associant au fichier physique SonNom. Procedure SupprimeFichier ( SonNom : String ); Faire disparatre du disque le fichier de nom SonNom. procedure DuplicFichier ( NomOriginel , NomFinal : String ) ; Duplique le contenu du fichier disque dont le nom est NomOriginel vers celui dont le nom est NomFinal et supprime du disque le fichier NomOriginel.
Les fichiers -

18

Le code de chacune de ces procdures est fort simple. Procedure OuvreEnLecture ( Var F : Text ; SonNom : String ) ; Begin Assign ( F , SonNom ) ; Reset ( F ) End ; Procedure OuvreEnEcriture ( Var F : Text ; SonNom : String ) ; Begin Assign ( F , SonNom ) ; Rewrite ( F ) End ; Procedure SupprimeFichier ( SonNom : String ) ; Var F : Text ; Begin Assign ( F , SonNom ) ; Erase ( F ) End ; Procedure DuplicFichier ( NomOriginel , NomFinal : String ) ; Var F, G : Text ; C : Char ; Begin OuvreEnLecture ( F , NomOriginel ) ; OuvreEnEcriture ( G , NomFinal ) ; While Not Eof ( F ) Do Begin Read ( F , C ) ; Write ( G , C ) End ; Close ( F ) ; Close ( G ) ; SupprimeFichier ( NomOriginel ) End ; En reprenant l'exemple du fichier de nombres, avec un nombre par ligne, voici la procdure d'ajout d'un nouveau nombre la fin de ce fichier. Notez le choix d'un nom suffisamment exotique pour le fichier temporaire afin de ne pas dtruire un fichier qui existerait sur le disque...

Les fichiers - 19

Procedure AjouteEnFin ( NomFichier : String ; UnNombre : Integer ) ; Var F , Tempo : Text ; X : Integer ; Begin OuvreEnLecture ( F , NomFichier ) ; OuvreEnEcriture ( Tempo , 'ABC.$$$' ) ; While Not Eof ( F ) Do {recopie d'abord tout le fichier original } Begin Readln ( F , X ) ; Writeln ( Tempo , X ) { dans le fichier temporaire} End ; Writeln ( Tempo , UnNombre ) ; { puis crit le nouveau nombre la suite} Close ( F ) ; Close ( Tempo ) ; DuplicFichier ( 'ABC.$$$' , NomFichier ) { recopie du temporaire { vers l'original et destruction } { du fichier temporaire } End ; exercice 7.1 : le Turbo Pascal possde une primitive non standard nomme Append, qui permet d'ouvrir un fichier texte existant en criture sans le dtruire et de se positionner directement la fin. Exploiter cette primitive pour obtenir une version plus simple de AjouteEnfin. exercice 7.2 : sur le modle prcdent crire une procdure AjouteEntete qui insre un nouveau nombre pass en paramtre au dbut d'un fichier texte. exercice 7.3 : sur le modle prcdent crire une procdure AjouteApres qui insre un nouveau nombre aprs un autre nombre ( passs en paramtre ) contenu dans un fichier texte. exercice 7.4 : sur le modle prcdent crire une procdure AjouteAvant qui insre un nouveau nombre avant un autre nombre ( passs en paramtre ) contenu un fichier texte. exercice 7.5 : comment se comportent les deux procdures prcdentes si le nombre aprs ou avant lequel il faut ajouter le nouveau existe plusieurs fois dans le fichier texte ? Comment rsoudre ce problme ? La suppression d'une information de notre fichier de nombres est trs similaire. Il faut recopier l'originel dans le temporaire, sauf les nombres qui seraient trouvs gaux celui que l'on cherche liminer. Notez le paramtre supplmentaire Ok qui vaudra Vrai en sortie si l'on a ralis au moins une suppression.

Les fichiers -

20

Procedure SupprimeTout ( NomFichier : String ; UnNombre : Integer ; Var Ok : Boolean ) ; { supprime toutes les occurrences de UnNombre } Var F , Tempo: Text ; X : Integer ; Begin OuvreEnLecture ( F , NomFichier ) ; OuvreEnEcriture ( Tempo , 'ABC.$$$' ) ; Ok := False ; While Not Eof ( F ) Do { tant que l'on a pas atteint la fin du fichier } Begin Readln ( F , X ) ; If X <> UnNombre Then { on ne recopie que les nombres diffrents } Writeln ( Tempo , X ) { de celui supprimer } Else Ok := True { on l'a trouv, donc on ne recopie pas et } { on indique le succs } End ; Close ( F ) ; Close ( Tempo ) ; DuplicFichier ( 'ABC.$$$' , NomFichier ) End ; exercice 7.6 : sur le modle ci-dessus, crire une procdure nomme SupprimeNieme qui supprime la Nieme occurrence d'un certain nombre d'un fichier texte. En dduire une nouvelle version de SupprimeTout. Quelle est son temps dexcution par rapport la version ci-dessus ? exercice 7.7 : de faon analogue crire des procdures nommes RemplaceNieme et RemplaceTout qui remplacent la Nieme occurrence ou toutes les occurrences d'un certain nombre par une nouvelle valeur dans un fichier texte. Une version plus subtile de DuplicFichier serait de ne pas recopier les contenus des fichiers, mais simplement d'changer leurs noms sur le disque. L'ide d'utiliser directement la procdure Rename du Turbo Pascal ne fonctionne pas, car il n'est pas possible daffecter un fichier un nom qui existerait dj sur le disque. Dans ce contexte d'appel, NomOriginel reprsente le nom 'ABC.$$$' et NomFinal 'NB10A20.TXT' et ces deux fichiers existent rellement sur le disque. Procedure DuplicFichier ( NomOriginel , NomFinal : String ) ; { fausse } Var F : Text ; Begin Assign ( F , NomOriginel ) ; Rename ( F , NomFinal ) End ; D'ou la version suivante o l'on commence par supprimer du disque le fichier ayant le nom NomFinal ( 'NB10A20.TXT' ) puis on renomme le fichier ABC.$$$ en NB10A20.TXT. Bien sr cette procdure ne doit tre appele que dans un contexte o le nom spcifi par NomOriginel existe bien sur le disque, ce qui est notre cas.

Les fichiers - 21

Procedure DuplicFichier ( NomOriginel , NomFinal : String ) ; Var F : Text ; Begin Assign ( F , NomFinal ) ; Erase ( F ) ; Assign ( F , NomOriginel ) ; Rename ( F , NomFinal ) End ; Une version beaucoup plus gnrale est la suivante. Pour renommer un fichier en un autre il faut essayer de supprimer le nouveau nom du disque, au cas o il existerait, ignorer l'erreur s'il n'existait pas et raliser enfin le renommage. Procedure DuplicFichier ( NomOriginel , NomFinal : String ) ; Var F : Text ; Begin Assign ( F , NomFinal ) ; {$I-} { pas d'arret sur erreur } Erase ( F ) ; If IoResult <> 0 Then ; { si il y a eu erreur tant pis } Assign ( F , NomOriginel ) ; Rename ( F , NomFinal ) ; If IoResult <> 0 Then { si il y a eu erreur tant pis } {$I+} { retour la normale } End ;

8 Les fichiers textes pour l'change de donnes


Comme nous lavons dj signal, lintrt majeur des fichiers textes est de permettre lchange dinformations entre des programmes diffrents. Par exemple, le logiciel tableur Excel est capable de relire directement le contenu d'un fichier texte organis en lignes. Les valeurs placer dans les diffrentes colonnes de chaque ligne Excel doivent tre spares par une tabulation ( le caractre de code ASCII 9 ). Si nous avions fabriqu un fichier texte avec un nom, un prnom et une note par ligne, il est possible de le rcuprer directement avec Excel comme le montre la bote de dialogue Ouvrir cidessous :

Les fichiers -

22

Les donnes peuvent alors tre traites sous Excel ( tries, harmonises, etc. ).

Excel peut enfin enregistrer de nouveau cette feuille de calcul modifie au format texte avec divers sparateurs comme le montre la bote de dialogue Enregistrer sous ci-dessous :

Les fichiers - 23

Pour notre fichier, nous obtiendrons le contenu suivant : nom prnom note dubois roger durand michel dupont ren duval pierre martin paul

8 4 12 14 10

exercice 8.1 : crire un programme en Turbo Pascal qui cre un fichier texte contenant sur chaque ligne un nom, un prnom et une note. Relire le fichier avec Excel et calculer la somme, moyenne et cart-type de ces notes. exercice 8.2 : crer avec Excel un fichier texte contenant une colonne de noms, une colonne de prnoms et une colonne de notes. Relire ce fichier avec un programme Pascal qui affichera les nom, prnom et note et calculera la moyenne des notes.

9 Priphriques dans Turbo Pascal


Turbo Pascal et le systme d'exploitation MsDos considrent les quipements externes tels que le clavier, l'cran et l'imprimante comme des priphriques. Du point de vue du programmeur, un priphrique est trait comme un fichier texte et les oprations sont excutes avec les mmes procdures et fonctions. Les priphriques MsDos sont implments grce des noms de fichiers rservs ayant une signification particulire. En ralit, Turbo Pascal n'a pas conscience du fait qu'une variable fichier se rfre un priphrique plutt qu' un fichier sur disque. Par exemple, le programme crira la chane de caractres 'Hello la plante...' sur l'imprimante, bien que la syntaxe utilise soit exactement la mme que pour un fichier sur disque. Var Sortie : Text ; Begin Assign ( Sortie , 'LPT1:' ) ; Rewrite ( Sortie ) ; Writeln ( Sortie , 'Hello la plante...' ) ; Close ( Sortie )
Les fichiers -

24

End . Nous donnons ci-dessous la liste des priphriques MSDOS les plus connus : Le priphrique sans nom Ce priphrique correspond la console, qui permet d'envoyer des informations vers l'cran et d'en recevoir partir du clavier. Les fichiers standard Input et Output et tous les fichiers assigns un nom de fichier vide se rfrent implicitement ce priphrique. Lorsque les entres et les sorties ne sont pas rediriges, Input et Output sont automatiquement ouverts au dbut du programme. De la mme manire, Input et Output sont automatiquement referms la fin du programme. Tous les ordres Read et Write sans paramtres indiquant le nom du fichier se rfrent ce priphrique. Dans le cas de redirection des entres-sorties au niveau de MsDos, il suffit dassocier InputOutput au priphrique sans nom pour que toutes les entres-sorties cran-clavier sadressent aux fichiers redirigs. Par exemple, le programme suivant ( REDIR.PAS ) vous demande votre nom et vous salue. Program Redirection ; Var Nom : String ; Begin { prise en compte dune ventuelle rdirection par MsDos } Assign ( Output , '' ) ; Rewrite ( Output ) ; Assign ( Input , '' ) ; Reset ( Input ) ; Writeln ( votre nom ) ; Readln ( Nom ) ; Writeln ( Bonjour , Nom ) ; Close ( Output ) ; Close ( Input ) End . Si vous le lancer par REDIR, vous verrez apparatre lcran la question, vous rpondrez au clavier et le salut saffichera lcran. Si vous le lancer par REDIR > BONJOUR.TXT , tous les ordres Writeln se feront vers un fichier texte BONJOUR.TXT. par contre vous devrez taper au clavier votre nom. Si vous le lancer par REDIR > BONJOUR.TXT < MOI.TXT , il cherchera lire votre nom dans le fichier MOI.TXT puis dposera la rponse dans le fichier BONJOUR.TXT. Les priphriques LPT1, LPT2 et LPT3 La famille de priphriques LPTx concerne les trois imprimantes que vous pouvez utiliser sur votre systme. Pour la premire imprimante, vous pouvez utiliser le synonyme PRN. Note : l'unit standard Printer contient la dclaration d'une variable de fichier texte appele Lst qu'elle associe au priphrique LPT1. Pour facilement crire quelque chose sur l'imprimante depuis l'un de vos programmes, il vous suffit d'inclure l'unit Printer dans la clause Uses du programme et d'utiliser Write ( Lst , ... ) ou Writeln ( Lst , ... ).

Les fichiers - 25

Les priphriques COM1 et COM2 Les priphriques de communication concernent les deux ports de communication srie. Le synonyme AUX peut tre utilis pour COM1. Ce priphrique est peu exploitable tel quel car MsDos gre trs mal la communication travers les ports srie. Le priphrique NUL Ce priphrique ignore toute criture et gnre une fin de fichier immdiate lorsque vous essayez d'en lire le contenu. Vous l'utiliserez lorsque vous ne voudrez pas crer de fichier particulier, alors que le programme dsire tout de mme une entre ou une sortie d'information. Le programme suivant montre l'emploi des priphriques pour sortir volont le contenu d'un fichier typ nomm PRODUITS.DAT vers lcran, limprimante ou un vritable fichier texte ( PRODUITS.TXT ). Program ListProducFile ; Type { dclarations articles du fichier binaire } tProduit = Record Nom : String [ 80 ] ; CodeProduit : Integer ; Quantite : Real ; CodeFourni : Integer ; End ; Var FicProduits : File Of tProduit ; { le fichier binaire} Produit : tProduit ; { tampon de lecture } Sortie : Text ; { le fichier texte de sortie} Rep : Char ; Begin Assign ( FicProduits , 'PRODUITS.DAT' ) ; Reset ( FicProduits ) ; Writeln ( sortie vers Ecran Imprimante Fichier (E I F )) ; Repeat Readln ( Rep ) Until Upcase ( Rep ) In [ E , I , F ] ; Case Rep Of E , e : Assign ( Sortie , ) ; { vers lcran fichier anonyme} I , i : Assign ( Sortie , PRN ) ; { PRN : nom de limprimante} F , f : Assign ( Sortie , PRODUITS.TXT ) { un vrai fichier texte} End ; Rewrite ( Sortie ) ; Writeln ( Sortie , Code Produit:10 , Nom :20 , Quantit:20 , Code Fournisseur:10 ) ; While Not Eof ( FicProduits ) Do Begin Read ( FicProduits , Produit ) ; With Produit Do Writeln ( Sortie , CodeProduit:10 , Nom:20 , Quantite:20:2 , CodeFourni:10 ) End ; Close ( FicProduits ) ; Close ( Sortie ) ; End .
Les fichiers -

26

10 Les fichiers binaires en Turbo Pascal 10.1 Ouverture et fermeture des fichiers binaires
Tout comme avec les fichiers textes, une variable fichier binaire doit avoir t associe un fichier externe avec Assign, puis tre ouverte par Reset ou Rewrite. Notez que les procdures Reset et Rewrite ont un comportement identique celles des fichiers textes mais que dans les deux cas le fichier sera ouvert en lecture et criture. La procdure Append nest pas permise avec ce type de fichier. Il est regrettable que Turbo Pascal nait pas une procdure spcifique douverture dun fichier binaire avec cration automatique si ncessaire. Un problme srieux est celui de la cration du fichier lors de la premire excution dun programme. La premire fois, le fichier doit tre cr avec un appel Rewrite, qui reste la seule mthode pour crer un fichier vide. Un appel Reset conduirait une erreur dexcution puisque le fichier nexiste pas encore sur le disque. Par contre, ds la seconde excution il faut imprativement faire appel Reset pour ouvrir simplement le fichier sans en dtruire le contenu qui aurait t dpos lexcution prcdente. Comment un programme peut-il savoir si cest la premire fois quil est utilis ? La mthode standard est la suivante. On dsactive les erreurs dentre-sortie, puis on essaie dutiliser Reset. Sil y a eu une erreur, cest que le fichier nexistait pas et on le cre avec Rewrite : Assign ( F , SonNom ) ; {$I-} Reset ( F ) ; If IOresult <> 0 Then Rewrite ( F ) ; {$I+}

{ cration }

Lappel Close reste lunique mthode pour refermer un fichier. La variable interne redevient disponible pour une autre association ou une ouverture du mme fichier externe dans un autre mode. La procdure Flush qui permettait de forcer une criture physique du tampon vers le disque nexiste plus avec les fichiers binaires. Pour la remplacer il faut refermer le fichier et le r-ouvrir de nouveau par : Close ( F ) ; Reset ( F ) A la diffrence de Flush, cette opration remet le pointeur de fichier au dbut du fait de lappel Reset.

10.2 Fonctions d'tats sur les fichiers binaires


De faon interne, un fichier binaire peut tre considr comme un tableau hors mmoire de composantes de mme type. Par analogie avec une simple bote fiches, nous nommerons fiche une composante. Chaque fiche est repre par un indice variant de 0 la taille du fichier moins 1. La valeur de cet indice, nomm le pointeur de fichier est prive au type File et ne peut pas tre manipule directement. Le type de cet indice est Longint ( entier long cod sur 32 bits ) soit une valeur maximale de 231 - 1 ( environ 2 milliards ) puisque lindice ne peut tre ngatif.

Les fichiers - 27

A chaque opration de lecture ou dcriture la valeur du pointeur de fichier est automatiquement incrmente. On le manipule travers une srie de procdures et fonctions comme : Function FilePos ( Var F : File ) : Longint ; Fonction entire retournant la valeur actuelle du pointeur de fichier. Avec un fichier qui vient dtre ouvert la valeur est zro. Function FileSize ( Var F : File ) : Longint ; Fonction entire retournant la taille d'un fichier disque exprime en nombre de fiches. Elle correspond donc la valeur maximale que lon peut affecter au pointeur de fichier. Si FileSize est gale 0 le fichier est vide. Pour retrouver la taille exacte en octets dun fichier ( comme affiche par le catalogue de la disquette ) il faut donc multiplier FileSize ( F ) par la taille en octets de chaque fiche obtenue partir de sa dclaration de type composante ou grce la fonction standard Sizeof. Var F : File Of Integer ; ...... Write ( taille du fichier en octets gale = ) ; Writeln ( FileSize ( F ) * 2 ) ) ; ou mieux Writeln ( FileSize ( F ) * Sizeof ( Integer ) ) ;

Procedure Seek ( Var F : File ; N : Longint ) ; Seek dplace le pointeur de fichier sur la Nieme fiche du fichier rfrenc par F. N est une expression entire de type entier long ( Longint ). La position de la premire fiche est 0. Donc linstruction Seek ( F , 0 ) permet de se replacer au dbut du fichier. Pour pouvoir agrandir un fichier on doit dplacer le pointeur juste aprs la dernire fiche et crire cet endroit. On utilise la construction suivante : Seek ( F , FileSize ( F ) ) ; FileSize retourne le nombre de fiches d'un fichier et comme les lments commencent au numro 0, le nombre retourn est le rang du dernier composant plus 1. A cet endroit il nest possible que dcrire puisque lon se trouve au-del de la fin physique du fichier. Function Eof ( Var F : File ) : Boolean ; Applique un fichier binaire, la fonction Eof retourne Vrai si le pointeur de fichier est positionn aprs la dernire composante dun fichier. Cest dire si FileSize est gal FilePos. Eof reste toujours Vrai sur un fichier ouvert avec Rewrite. La construction suivante permet un traitement global dun fichier binaire ouvert. Notez notre choix de la boucle TantQue plutt que Rpter Jusqu qui permet dviter un grave problme de lecture impossible si le fichier tait initialement vide : Seek ( F , 0 ) ; While Not Eof ( F ) Do Begin { instructions de lecture dune information} { instructions de traitement de cette information } End ;
Les fichiers -

28

Nous prfrons cette construction la suivante qui est quivalente, mais utilise une variable I supplmentaire : Var I : Longint ; ... For I := 0 To FileSize ( F ) - 1 Do Begin Seek ( F , I ) ; { lire et traiter la composante courante } End ; Procedure Truncate ( Var F : File ) ; Coupe le fichier la position courante ( dfinit cette position en tant que fin du fichier ). Noter quil sagit de lunique moyen de rduire la taille dun fichier disque sans le recopier dans un autre. La squence suivante dtruit la dernire fiche dun fichier et rduit donc sa taille sur le disque dune fois la taille dune fiche. Seek ( F , FileSize ( F ) - 1 ) ; Truncate ( F ) Celle-ci dtruit lensemble du contenu dun fichier. Elle est quivalent Rewrite ( F ) : Seek ( F , 0 ) ; Truncate ( F )

10.3 Entre et sortie de composantes


Les fichiers binaires utilisent les primitives Read ou Write pour changer des composantes ( fiches ) entre des variables du type appropri et le fichier physique. Readln et Writeln ne sont pas autoriss car il ny a pas de conversion binaire texte dans ce cas. Procedure Read ( Var F : File ; Var C ) ; La procdure Read permet la lecture de composantes depuis le fichier. Le type de la variable C doit tre exactement identique celui cit dans la dclaration File Of de la variable fichier F. La squence suivante traite lensemble des fiches dun fichier suppos tre de type tFiche :

Les fichiers - 29

{ lecture des enregistrements dun fichier binaire } Type tFiche = Record Nom , Prenom : String ; Age : Integer End ; Var Fiche : tFiche ; F : File Of tFiche ; ... Seek ( F , 0 ) ; While Not Eof ( F ) Do Begin Read ( F , Fiche ) ; Traiter ( Fiche ) End ; Notez quil nest pas permis de lire une partie dune composante. La construction suivante sera rejete par le compilateur avec une erreur de type : Var F : File Of tFiche ; Fiche : tFiche ; ... Read ( F , Fiche.Nom ) ; Si lon a besoin de consulter le nom dune personne, il faut lire lintgralit de cette fiche dans une variable du type appropri puis en extraire le nom. Lexemple suivant affiche les noms inscrits sur toutes les fiches dun fichier dclar comme ci-dessus : Seek ( F , 0 ) ; While Not Eof ( F ) Do Begin Read ( F , Fiche ) ; Writeln ( Fiche.Nom ) End ; Comme nous lavons dj signal, il importe quil y ait une correspondance exacte entre le type rel des fiches contenues dans un fichier et la dclaration qui en est faite en Pascal. Si vous ignorez le type des fiches, il est impossible dexploiter le fichier. Rien ne vous interdit de crer un fichier avec un certain type de fiche et de le relire ultrieurement avec un autre. Mais il est plus que probable que le traitement du fichier se passera trs mal ; soit parce que les valeurs binaires lues nauront aucun rapport soit parce que vous attendrez inopinment la fin du fichier au beau milieu dune lecture parce que la taille dclare de chaque fiche ne correspondra pas la ralit. exercice machine 10.3.1 : crer un fichier binaire contenant une dizaine de nombres rels ( File Of Real ). Puis relire ce fichier comme un File Of LongInt et un File Of Integer. exercice machine 10.3.2 : crer un fichier contenant des fiches de type Nom, Prenom : String [ 10 ] puis relire ce fichier comme un fichier de type Nom, Prenom : String [ 10 ] ; Age : Integer. Que constatez -vous ? Que faudrait-il faire pour ajouter le champ ge chaque fiche du fichier ?

Les fichiers -

30

Procedure Write ( Var F : File ; C ) ; La procdure Write permet dcrire des fiches la position courante dans le fichier. Le type de la variable C doit tre exactement identique celui cit dans la dclaration File Of de la variable fichier F. Comme avec Read, il y a avance automatique du pointeur de fichier la fiche suivante. Il est de nouveau interdit dcrire une partie dune fiche. Lexemple suivant ajoute un an lge de toutes les fiches de type ( nom, prnom, ge ) du fichier suppos ouvert : Seek ( F , 0 ) ; While Not Eof ( F ) Do Begin Read ( F , C ) ; C.Age := C.Age + 1 ; Seek ( F , FilePos ( F ) - 1 ) ; Write ( G , C ) ; End ; exercice 10.3.3 : quel est le but de linstruction Seek ( F , FilePos ( F ) - 1 ) dans lexemple cidessus ?

11 Modifications du contenu de fichiers binaires


Le fait que les fichiers binaires soient trs similaires des tableaux pourrait laisser penser que les algorithmes habituels de mise jour de linformation ( ajouts, suppressions, modifications, etc. ) leur sont applicables ; ces algorithmes sont dtaills dans le chapitre 3 ( Mthodologie de dveloppement ). Ceci est probablement vrai avec de petits fichiers mais certainement pas avec des applications en grandeur relle. La diffrence majeure est quun fichier ne rside pas en mmoire mais sur un disque. La taille dun fichier est souvent beaucoup trop importante pour que lon puisse envisager de le lire en mmoire dans un tableau ( ou une autre structure de donnes ) pour le traiter avec un algorithme classique puis de rcrire le rsultat sur le disque. Les algorithmes utiliser doivent donc travailler une fiche la fois, avec dincessants changes entre une variable de type tFiche et la composante correspondante du fichier. Ces oprations sont longues et dangereuses puisque durant tout le traitement le fichier est ouvert et reste vulnrable. Toute anomalie de fonctionnement du matriel ou du logiciel le laisserait dans un tat irrcuprable. De plus, au contraire dun tableau o lon peut aisment grer le nombre maximal de composantes, se pose dans le cas des fichiers le problme de la capacit disque quil convient de surveiller avant de tenter tout agrandissement ou toute recopie dun fichier. Imaginons linsertion dune fiche dune centaine de caractres (nom, prnom, adresse et code postal ) au dbut dun fichier de 10000 adresses. Cette opration ncessite : - soit, en exploitant laccs direct, le dcalage des 10000 fiches dune position vers le bas cest-dire 10000 lectures et 10000 critures. Avec un disque dur rapide ( temps d'accs 10ms, temps dcriture dun octet 0.02 ms ) ces oprations prendraient 20000 * 10ms ( accs ) + 10000 * 100 * 0.02ms ( lecture ) + 10000 * 100 * 0.02 ms ( criture ) soit 240 secondes ( 3 minutes ! )
Les fichiers - 31

- soit, comme nous lavons fait avec les fichiers textes, la cration dun second fichier sur lequel on crira dabord la nouvelle fiche puis ou lon recopiera la suite le contenu du fichier originel ( 10000 lectures et 10000 critures de nouveau ). Cette mthode aura lavantage de la sret puisque lon aura toujours sur le disque la copie de loriginal. En esprant quil y aura sur le disque suffisamment de place pour deux copies du fichier. Sans compter lobligation de recopier le nouveau fichier sur lancien, ou si le systme le permet, de dtruire lancien fichier et de renommer le nouveau. Ces temps devront tre multiplis par plusieurs dizaines si lon effectue un tri de ce fichier, cest--dire par des oprations rptes dinsertion et de dcalages des fiches pour les mettre leur place dans lordre dsir. Pour viter toute rorganisation, les fiches sont systmatiquement ajoutes la fin du fichier par la construction suivante: Seek ( F , FileSize ( F ) ) ; Write ( F , NouvelleFiche ) ) ; Le fichier ne peut donc pas tre tri selon un critre de recherche. Il nest plus possible dutiliser des algorithmes de recherche plus performants ( dichotomie, recherche avec sentinelle, etc. ). Lalgorithme de recherche doit donc tre de type squentiel et ne permet donc de trouver que la premire fiche ayant le critre recherch. Il est donc capital que chaque fiche contienne une cl unique dans tout le fichier ( code produit, nom + prnom... ) et lunicit de cette cl doit tre maintenue lors des ajouts et des modifications. Si on dsire un ordre, il convient dassocier au fichier principal une table d'accs trie ( index ) que lon sauvera dans un second fichier et qui devra tre mis jour lors de chaque modification du fichier principal ( technique du squentiel index ). Le fichier nest pas ordonn mais lindex le sera. Cette table devra contenir pour chaque fiche la valeur de sa cl et le numro de la fiche correspondante dans le fichier. Les recherches se feront alors exclusivement sur cette table qui dlivrera en retour le numro de la fiche cherche. Il est possible davoir plusieurs tables d'accs et donc plusieurs critres de recherche pour un mme fichier ( exemple : le fichier des critures dune comptabilit que lon pourrait rechercher par numro de compte, date ou journal dimputation ). Le problme de la suppression est aussi dlicat grer. Il nest pas raisonnable de recopier le fichier dans un autre en oubliant la fiche supprimer, ni de dcaler dune place vers le haut les fiches suivantes. La mthode propose ici est de marquer la fiche comme supprime en mettant une valeur particulire dans une de ses rubriques. Elle est trs efficace en temps ( 2 accs disque ). Elle a nanmoins comme dsavantage de laisser dans le fichier des trous , et donc dencombrer inutilement le disque. Deux amliorations sont possibles : - soit de compacter priodiquement le fichier en ne recopiant que les fiches restant valides. Ceci a lavantage de permettre dannuler une suppression tant que ce compactage na pas eu lieu. - soit de modifier lalgorithme dajout pour quil recherche dabord un trou avant de mettre la fiche en fin de fichier. Le mme algorithme que la recherche pourrait tre utilis si la marque est une valeur particulire ( et impossible normalement ) dune des rubriques de la fiche. Une mthode frquemment utilise est dinscrire dans la premire fiche du fichier ( qui ne contient donc pas linformation normale ) le numro de fiche du premier trou ou -1 sil ny en a aucun. Le premier trou contient le numro du suivant et ainsi de suite jusquau dernier qui contient 1. On constitue ainsi dans le fichier lui-mme une liste chane des trous. On peut donc trouver sans recherche squentielle la position du premier trou en consultant simplement la premire fiche. En cas de rcupration dun trou, on rcupre le premier de la liste et on met jour la premire fiche pour quelle contienne le numro du trou suivant ( ou -1 ) si ce trou tait le dernier.
Les fichiers -

32

Bien entendu, les algorithmes de balayage squentiel du fichier ( recherche, impression, recopie, etc. ) doivent tester que la fiche courante nest pas marque comme supprime.

12 Les fichiers non typs


Dans le cas des fichiers non typs, les procdures Reset et Rewrite acceptent un paramtre supplmentaire optionnel permettant de spcifier la taille dune fiche utilise lors des transferts. Pour des raisons historiques, la taille par dfaut est de 128 octets. La taille conseille est de 1 octet ; c'est en effet la seule valeur qui permette de manipuler correctement un fichier de n'importe quelle taille ( aucun enregistrement incomplet n'est redouter lorsque la taille est de 1 ). Var F : File ; Assign ( F , PRODUIT.DTA ) ; Reset ( F ,1 ) ; ou Reset ( F ) ; ou Reset ( F , Sizeof ( tInfo ) ) ;

{ prt pour un accs 1 octet la fois} { prt pour un accs 128 octets la fois} { prt pour un accs une fiche la fois}

Toutes les procdures et les fonctions de manipulation de fichiers, except Read, Write sont autorises sur les fichiers sans type. Read et Write sont remplacs par deux procdures BlockRead et BlockWrite qui attendent comme paramtre supplmentaire le nombre de fiches lire ou crire. La syntaxe d'appel ces procdures est : BlockRead ( Var F : File ; Var V ; NbALire : Integer ) ; BlockWrite ( Var F : File ; Var V ; NbAEcrire : Integer ) ; ou BlockRead ( Var F : File ;Var V ; NbALire : Integer ; Var NbLus : Integer ) ; BlockWrite ( Var F : File ; Var V ; NbAEcrire : Integer ; Var NbEcrits : Integer ) ; F est une variable de fichier sans type, V est toute variable et NbALire ( ou NbAEcrire ) est une expression entire donnant le nombre de fiches ( dont la taille a t dfinie par le second paramtre de Reset ou Rewrite ) transfrer entre le fichier disque associ F et la variable V. Le paramtre facultatif NbLus ( ou NbEcrits ) retourne le nombre de fiches rellement transfres. Le transfert commence avec le premier octet occup par la variable V. Le programmeur doit s'assurer que la variable V a suffisamment d'espace pour le transfert tout entier. Un appel BlockRead ou BlockWrite avance le pointeur de fichier de NbLus ( ou NbEcrits ) enregistrements. La fonction Eof fonctionne comme pour les fichiers typs, ainsi que les fonctions FilePos, FileSize et la procdure Seek qui utilisent la taille dune fiche comme spcifie par le programmeur dans Reset ou Rewrite ( ou 128 par dfaut ). Le programme suivant utilise des fichiers sans type pour dupliquer nimporte quel fichier. Remarquez l'emploi du quatrime paramtre facultatif, avec BlockRead, pour suivre le nombre d'enregistrements lus dans le fichier source et donc la fin de la copie :

Les fichiers - 33

Program CopieDeFichiers ; Const TailleTampon = 10000 ; { taille du tampon dchange}

Type tTampon = Array [ l..TailleTampon ] Of Byte ; Var Source , Dest : File ; SourceName , DestName : String ; Tampon : tTampon ; NbRecsLus : Integer ; { les deux fichiers sans type} {les deux nomes externes} { le tampon dchange} { contrle du nombre octets lus}

Begin Write ( 'nom du fichier source ') ; Readln ( SourceName ) ; Assign ( Source , SourceName ) ; { prt la lecture du fichier source } Reset ( Source , 1 ) ; { 1 octet la fois ,doit exister } Write ( 'nom du fichier destination ' ) ; Readln ( DestName ) ; Assign ( Dest , DestName ) ; { prt lcriture du fichier destinat.} Rewrite ( Dest , 1 ) ; { 1 octet la fois, doit tre nouveau } Repeat { lire TailleTampon enregistrements dans le fichier source vers le tampon } { soit ici 10000 * 1 octets } BlockRead ( Source , Tampon , TailleTampon , NbRecsLus ) ; { et recopier dans le fichier destination le nombre effectivement lus } If NbRecLus > 0 Then BlockWrite ( Dest , Tampon , NbRecsLus ) Until NbRecsLus = 0 ; { plus rien lire dans la source} Close ( Source ) ; Close ( Dest ) End . La mise la disposition des programmeurs de primitives de bas niveau ( BlockRead, BlockWrite... ) et de types gnriques ( File.. ) est caractristique de lvolution du langage Pascal dans ses versions modernes. En annulant ou en rduisant les contrles de type normalement effectus par le compilateur, on ajoute une plus grande souplesse dutilisation au langage et on rduit de ce fait la diffrence avec les langages dit professionnels comme C . Leffort du concepteur a t pratiquement nul puisque les primitives de plus haut niveau ( Read, Write... ) appellent en fait celles de plus bas niveau avec les paramtres calculs automatiquement par le compilateur partir du type des objets manipuls. Read ( F , C ) ; est quivalent BlockRead ( F , C , Sizeof ( C ) , NbLus ) ; If NbLus <> Sizeof ( C ) Then Ioresult := une valeur <> 0

Les fichiers -

34

Write ( F , C ) ; est quivalent BlockWrite ( F, C , Sizeof ( C ) , NbEcrits ) ; If NbEcrits <> Sizeof ( C ) ) Then Ioresult := une valeur <> 0 Un autre intrt des fichiers sans type est de pouvoir mettre dans un mme fichier des informations de type diffrent, ce qui nest pas possible avec un fichier binaire typ. Bien entendu, chaque fiche devra tre prcde dun indicateur de son type ( et ventuellement du nombre de fois o elle est prsente ) afin den permettre la relecture plus tard par un ordre BlockRead adapt. Cette mthode permet de crer des fichiers nomms des flots ( streams ) o des informations diverses sont crites la suite les unes des autres sans aucun contrle de type par le langage. On retrouve donc un des avantages des fichiers textes sans souffrir de la lenteur de la conversion binaire - texte et en bnficiant de la confidentialit de linformation puisquelle ne pourra tre ni lue ni modifie par un autre programme que le notre, puisquelle sera en binaire. exercice 12.1(***) : un programme de dessin dsire relire dans un unique fichier des objets graphiques de type diffrents comme: une ligne tLigne = Record X1 , Y1 , Y2 , Y2 : Integer End ; un rectangle tRect = Record X , Y , L , H : Integer End ; un cercle tCercle = Record X , Y , R : Integer End ; un point tPoint= Record X , Y : Integer End ; ..... les objets sont stocks dans le fichier sans aucun ordre et chacun est prcd dun entier indiquant son type ( 0 = point, 1 = Ligne, 2 = rectangle, 3 = cercle ). Ecrire un programme Pascal qui dessine la figure contenue dans le fichier DESSIN.DAT.

Les fichiers - 35