Google Plus

الصفحات

Affiliate Program ”Get Money from your Website”
Get Traffic Like Spam

الاثنين، 3 أكتوبر 2011

Cours d'algorithmique N°8 : les fichiers séquentiels

Jusqu’à présent, les informations utilisées dans nos programmes ne pouvaient provenir que de deux sources : soit elles étaient inclues dans l’algorithme lui-même, par le programmeur, soit elles étaient entrées en cours de route par l’utilisateur. Mais évidemment, cela ne suffit pas aux besoins réels.
Imaginons que l’on veuille écrire un programme gérant un carnet d’adresses. D’une exécution à l’autre, l’utilisateur doit pouvoir retrouver son carnet à jour, avec les modifications qu’il y a apportées la dernière fois qu’il a exécuté le programme. Les données du carnet d’adresse ne peuvent donc être inclues dans l’algorithme, et encore moins être entrées au clavier à chaque nouvelle exécution !
Les fichiers sont là pour combler ce manque. Ils servent à stocker des informations de manière permanente, entre deux exécutions d’un programme. Car si les variables, qui sont je le rappelle des adresses de mémoire vive, disparaissent à chaque fin d’exécution, les fichiers, eux sont stockés sur des périphériques à mémoire de masse (disquette, disque dur, CD Rom…).
1. Organisation des fichiers texte
Il existe deux grandes variantes pour structurer les données au sein d’un fichier texte : la délimitation, ou les champs de largeur fixe. Reprenons le cas du carnet d’adresse ; Nous nous limiterons aux renseignements suivants : Nom, prénom, téléphone, e-mail. Les données, sur le fichier texte, peuvent être organisées ainsi :
Structure n°1
"Fonfec";"Sophie";0142156487;"fonfec@yahoo.fr"
"Zétofrais";"Mélanie";0456912347 ;"zétofrais@free.fr"
"Herbien";"Jean-Philippe";0289765194;"vantard@free.fr"
"Hergébel";"Octave";0149875231;"rg@aol.fr"
ou ainsi :
Structure n°2
FonfecSophie0142156487fonfec@yahoo.fr
ZétofraisMélanie0456912347zétofrais@free.fr
HerbienJean-Philippe0289765194vantard@free.fr
HergébelOctave0149875231rg@aol.fr

La structure n°1 est dite délimitée ; Elle utilise un caractère de délimitation, qui permet de repérer quand commence un champ et quand commence le suivant. Il va de soi que ce caractère de délimitation doit être strictement interdit à l’intérieur de chaque champ, faute de quoi la structure devient proprement illisible.
La structure n°2, elle, est dite à champs de largeur fixe. Il n’y a pas de caractère de délimitation, mais on sait que les x premiers caractères de chaque ligne stockent le nom, les y suivants le prénom, etc. Cela impose bien entendu de ne pas saisir un renseignement plus long que le champ prévu pour l’accueillir.
  • L’avantage de la structure n°1 est son faible encombrement en place mémoire ; il n’y a aucun espace perdu, et un fichier texte codé de cette manière occupe le minimum de place possible. Mais elle possède en revanche un inconvénient majeur, qui est la lenteur de la lecture. En effet, chaque fois que l’on récupère une ligne dans le fichier, il faut alors parcourir un par un tous les caractères pour repérer chaque occurrence du caractères de séparation avant de pouvoir découper cette ligne en différents champs.
  • La structure n°2, à l’inverse, gaspille de la place mémoire, puisque le fichier est un vrai gruyère plein de trous. Mais d’un autre côté, la récupération des différents champs est très rapide. Lorsqu’on récupère une ligne, il suffit de la découper en différentes chaînes de longueur prédéfinie, et le tour est joué.
A l’époque où la place mémoire coûtait cher, la structure délimitée était privilégiée. Mais depuis bien des années, la quasi-totalité des logiciels – et des programmeurs – optent pour la structure en champs de largeur fixe. Aussi, sauf mention contraire, nous ne travaillerons qu’avec des fichiers bâtis sur cette structure.
2. Types d’accès

On vient de voir que l’organisation des données au sein du fichier pouvait s’effecteur selon deux grands choix stratégiques. Mais il existe une autre ligne de partage des fichiers : le type d’accès, autrement dit la manière dont la machine va pouvoir aller rechercher les enregistrements.
On distingue :
  • L’accès séquentiel : on ne peut accéder qu’à l’enregistrement suivant celui qu’on vient de lire.
  • L’accès direct (ou aléatoire) : on peut accéder directement à l’enregistrement de son choix, en précisant le numéro de cet enregistrement.
A la différence de la précédente, cette typologie ne se reflète pas dans la structure elle-même du fichier. En fait, tout fichier, quelle que soit sa structure (délimité ou en largeur fixe) peut être utilisé avec l’un ou l’autre des deux grands types d’accès. Le choix du type d’accès n’est pas un choix qui concerne le fichier lui-même, mais uniquement la manière dont il va être traité par la machine. C’est donc dans le programme, et seulement dans le programme, que l’on choisit le type d’accès souhaité.
Au premier abord, il est clair que l’accès direct possède tous les avantages et aucun inconvénient. Sa programmation est immensément plus simple et moins fastidieuse que celle de l’accès séquentiel. Mais… vous vous doutez bien qu’il y a un mais.
Le gros problème de l’accès direct, c’est qu’il n’est pas géré de la même manière selon le type de machine. Car la gestion de l’accès direct suppose des éléments de langage " annexes ", qui diffèrent selon les ordinateurs et qui ne seront pas forcément présents. Pour résumer, disons que si vous écrivez un programme C utilisant des accès directs à des fichiers, vous n’êtes pas absolument certains que votre programme pourra tourner sur tous les ordinateurs.
En revanche, l’accès séquentiel, lui, est entièrement piloté par le langage lui-même. Il est donc laborieux à programmer, rustique, tout ce que vous voulez, mais il offre une sécurité absolue de portabilité. Voilà pourquoi la plupart des programmeurs s’astreignent encore à utiliser ce type d’accès, et voilà pourquoi c’est celui-là que nous allons étudier.
Et de toute manière, qui peut le plus peut le moins, et une fois que vous aurez maîtrisé la programmation de l’accès séquentiel, celle d l’accès direct vous apparaîtra comme une ineffable poilade.
3. Instructions

Si l’on veut travailler sur un fichier texte, la première chose à faire est de l’ouvrir. Cela se fait en attribuant au fichier un numéro de canal. On ne peut ouvrir qu’un seul fichier par canal, mais on dispose toujours de plusieurs canaux, dont pas de soucis.
L’important est que lorsqu’on ouvre un fichier, on stipule ce qu’on va en faire : lire, écrire ou ajouter.
  • Si on ouvre un fichier pour lecture, on ne pourra que récupérer les informations qu’il contient, sans les modifier en aucune manière.
  • Si on ouvre un fichier pour écriture, on pourra mettre dedans toutes les informations que l’on veut. Mais les informations précédentes, si elles existent, seront intégralement écrasées.
  • Si on ouvre un fichier pour ajout, on ne peut ni lire, ni modifier les infos existantes. Mais on pourra, comme vous commencez à vous en douter, ajouter de nouveaux enregistrements.
Au premier abord, ces limitations peuvent sembler infernales. Mais avec un peu d’habitude, on se rend compte qu’en fait on peut faire tout ce qu’on veut avec ces fichiers séquentiels.
Pour ouvrir un fichier texte, on écrira par exemple :
Ouvrir "Exemple.txt" sur 4 pour Lecture
Ici, "Exemple.txt" est le nom du fichier sur le disque dur, 4 est le numéro de canal, et ce fichier a donc été ouvert en lecture, Christine, j’crois qu’c’est clair.
Ouvrir "Exemple.txt" sur 4 en Lecture
Variables
Truc, Nom, Prénom, Tel, Mail en Caractères
Lire 4, Truc
Nom ï Mid(Truc, 1, 20)
Prénom ï Mid(Truc, 21, 15)
Tel ï Mid(Truc, 36, 10)
Mail ï Mid(Truc, 46, 20)
L’instruction Lire récupère donc dans la variable spécifiée l’enregistrement suivant dans un fichier. Suivant par rapport à quoi ? Par rapport au dernier enregistrement lu. C’est en cela que le fichier est dit séquentiel.
Lire un fichier séquentiel de bout en bout suppose donc de programmer une boucle. Comme on sait rarement combien d’enregistrements comporte le fichier, la combine consiste à utiliser la fonction EOF (acronyme pour End Of File). Cette fonction est vraie si on a atteint la fin du fichier (auquel cas une lecture supplémentaire déclencherait une erreur. L’algorithme ultra classique en pareil cas est donc :
Variable Truc en Caractère
Ouvrir
"Exemple.txt" sur 5 en Lecture
Tantque Non EOF(5)
Lire
5, Truc
...
FinTantQue
Pour une opération d’écriture, ou d’ajout, il faut d’abord constituer une chaîne équivalente à la nouvelle ligne du fichier. Cette chaîne doit donc être " calibrée " de la bonne manière, avec les différents champs qui " tombent " aux emplacements corrects. Le moyen le plus simple pour s’épargner de longs traitements est de procéder avec des chaînes correctement dimensionnées dès leur déclaration (la plupart des langages offrent cette possibilité) :
Ouvrir "Exemple.txt" sur 3 en Ajout
Variable
Truc en Caractère
Variables
Nom*20, Prénom*15, Tel*10, Mail*15 en Caractère

Nom ï "Joker"
Prénom ï "Midnight"
Tel ï "0348946532"
Mail ï "allstars@rockandroll.com"
Truc ï Nom & Prénom & Tel & Mail
Ecrire
3, Truc
Et pour finir, une fois qu’on en a terminé avec un fichier, il ne faut pas oublier de fermer ce fichier. On libère ainsi le canal qu’il occupait (et accessoirement, on pourra utiliser ce canal dans la suite du programme pour un autre fichier… ou pour le même).
4. Stratégies de traitement

Il existe globalement deux manières de traiter les fichiers textes :
  • l’une consiste à s’en tenir au fichier proprement dit. C’est parfois un peu acrobatique, lorsqu’on veut supprimer un élément d’un fichier : on programme alors une boucle avec un test, qui recopie dans un deuxième fichier tous les éléments du premier sauf un ; et il faut ensuite recopier intégralement le deuxième dans le premier… Ouf.
  • l’autre consiste à passer par un ou plusieurs tableaux. On recopie l’intégralité du fichier de départ dans un tableau (en mémoire vive) et on ne manipule ensuite que ce tableau, qu’on recopie à la fin dans le fichier d’origine.
Les avantages de la seconde technique sont nombreux :
  • la rapidité : les accès en mémoire vive sont des milliers de fois plus rapides (nanosecondes) que les accès aux mémoires de masse (millisecondes au mieux pour un disque dur)
  • la facilité de programmation : ; bien qu’il faille écrire en plus les instructions de recopie du fichier dans le tableau, pour peu qu’on doive tripoter ces informations dans tous les sens, c’est largement plus facile de faire cela avec un tableau qu’avec des fichiers.
Pourquoi, alors, demanderez-vous haletants, ne fait-on pas cela à tous les coups ? Y a-t-il des cas où il vaut mieux en rester aux fichiers et ne pas passer par des tableaux ?
  • la recopie d’un gros fichier en mémoire vive consomme des ressources qui peuvent atteindre des dimensions considérables. Et au final, le gain de rapidité d’exécution risque de ne pas être évident.
  • si le fichier contient des données de type non homogènes (chaînes, numériques, etc.) cela risque d’être coton pour le stocker dans un tableau : il va falloir déclarer plusieurs tableaux, dont le maniement au final peut être aussi lourd que celui des fichiers de départ. Ou alors, il faut utiliser une ruse qu’offrent certains langages (mais pas tous) : créer des types de variables personnalisés, composés d’un " collage " de plusieurs types existants (10 caractères, puis un numérique, puis 15 caractères, etc.) Cette technique est un peu acrobatique. Bien qu’elle ne soit pas vraiment difficile, elle exige tout de même une certaine aisance.
Je rappelle qu’à priori, les fichiers textes ne sont pas là pour servir de bases de données (en tout cas dans des langages de programmation récents). Donc, on aura peu de chances (ou de risques) de se trouver devant des immenses fichiers textes, ne pouvant pas être mis en tableau. Mais ce n’est pas une règle : il faut donc bien comprendre les tenants et les aboutissants de chaque stratégie. Et pour cela, quoi de mieux que la pratique ?



0 commentaires:

إرسال تعليق

earn monye

شارك

Twitter Delicious Facebook Digg Stumbleupon Favorites More