Les fichiers
Les différents fichiers
1. Préambule
Vous me permettrez, pour une fois, d’être un peu direct : les fichiers sont une calamité à décrire en algorithmique. Durant des années, jusqu’au milieu des années 1990, le COBOL a régné en maître chez les langages de programmation en informatique de gestion. Ce langage était aussi puissant dans ce domaine que sa syntaxe était pratique. Ceux d’entre vous qui connaissent un peu le COBOL savent de quoi il est question ici. Une des sources de sa puissance était sa capacité à gérer les fichiers et les enregistrements structurés, dans tous les sens, dans tous les formats.
Seulement, le COBOL est passé de mode pour les nouveaux développements. Les multitudes de fichiers de données diverses et variées ont été remplacées par d’autres structures, notamment par des bases de données relationnelles, rendant caduque l’étude de la plupart des types de fichiers au profit de langages comme le SQL. Pourtant, les bases de données elles-mêmes sont souvent stockées dans des fichiers.
Aussi, ce chapitre est un peu plus court que les autres. Il serait possible de décrire une foule de types de fichiers : des livres complets existent sur ce thème, de plusieurs centaines de pages. Les bases et définitions théoriques seront cependant toutes couvertes. C# ne sachant pas directement (vous pouvez bien entendu tout reprogrammer, c’est son rôle) gérer des fichiers de type indexés, cela résout singulièrement le problème.
2. Problématique
Qu’est-ce qu’un fichier ? C’est exactement la même chose que dans la réalité. Quand vous avez une seule information à retenir dans votre tête, c’est facile. Quand vous en avez des milliers, c’est une mission impossible. Vous allez utiliser un agenda, rempli de fiches. Le cerveau a certes des capacités incroyables, mais comment retenir toutes les transactions bancaires de millions de comptes pour une banque ?
À cela, rajoutez deux problèmes :
-
Malgré la puissance de vos ordinateurs, la capacité mémoire reste souvent limitée. Un ordinateur 32 bits "standard" (bureau...
Les enregistrements
Ce chapitre se concentre sur les fichiers texte. Dans ceux-ci, vous devez définir la structure de vos enregistrements. Bien que tout soit possible, notamment avec des structures en arborescence comme le XML, vous pouvez initialement choisir entre deux méthodes assez simples : les enregistrements avec délimiteurs ou à largeur fixe.
1. Les délimiteurs
Les enregistrements délimités sont courants sous Unix. Dans chaque ligne, les valeurs individuelles sont appelées des champs et sont séparées entre elles par un caractère particulier appelé caractère de séparation ou caractère de délimitation, ou enfin délimiteur. N’importe quel caractère peut convenir, cependant il ne doit pas se retrouver dans la valeur d’un champ, ce qui aurait pour effet de casser la structure de l’enregistrement. Ce sont souvent le point-virgule ";" ou les deux points ":" qui sont utilisés.
Les champs d’enregistrements sont généralement encadrés par des guillemets lorsqu’il s’agit de chaînes de caractères, rien pour des valeurs numériques. Ce n’est pas une affirmation : ce n’est pas toujours le cas et c’est à vous de gérer le type d’une valeur donnée, au sein de votre programme.
Voici un simple exemple de contenu de fichier délimité de type courant sous Unix :
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/bin/bash
daemon:x:2:2:Daemon:/sbin:/bin/bash
lp:x:4:7:Printing daemon:/var/spool/lpd:/bin/bash
mail:x:8:12:Mailer daemon:/var/spool/clientmqueue:/bin/false
news:x:9:13:News system:/etc/news:/bin/bash
uucp:x:10:14:Unix-to-Unix CoPy system:/etc/uucp:/bin/bash
Les plus perspicaces d’entre vous auront reconnu un morceau du fichier Unix /etc/passwd qui contient quelques informations sur les comptes des utilisateurs du système Unix. Chaque ligne est un enregistrement dont la structure est la suivante :
-
Un séparateur ":" délimite les différents champs.
-
Il y a sept champs, numérotés (par convention) de 1 à 7.
-
1er champ : nom de l’utilisateur (son login).
-
2ème champ : indicateur de mot de passe (ici stocké ailleurs).
-
3ème champ :...
Fichier texte séquentiel
1. Ouvrir et fermer un fichier
Vous devez tout d’abord déclarer le nom logique du fichier, la variable qui permettra, associée au fichier, de travailler avec. Ceci se place comme d’habitude dans la section VAR. Vous indiquez ensuite le type d’accès : séquentiel, direct, indexé, etc. Notez qu’en accès direct, vous pouvez aussi travailler en mode séquentiel.
VAR
fic:fichier séquentiel
Vous devez ensuite ouvrir le fichier, en associant nom logique et nom du fichier, avec le mode d’ouverture souhaité. Ceci s’effectue avec l’instruction Ouvrir.
Ouvrir "toto.txt" dans fic en lecture
Vous trouverez aussi parfois cette syntaxe sous forme de fonction, plus proche de certains langages :
fic←Ouvrir("toto.txt","lecture")
La première syntaxe est souvent préférable en algorithmique. Pour fermer un fichier, utilisez l’instruction Fermer suivie du nom logique du fichier.
Fermer fic
Il existe aussi une syntaxe fonctionnelle, mais les mêmes remarques s’appliquent : utilisez la première en cas de doute.
Fermer(fic)
Ne placez pas le nom du fichier dans les instructions de lecture, écriture et de fermeture. Le programme ne connaît pas le nom du fichier, mais seulement son nom logique.
Aussi le début d’un éventuel programme ressemblerait à ceci :
Programme OUVRE
Var
fic :fichier séquentiel
nom :chaîne
Début
nom←"toto.txt"
Ouvrir nom dans fic en lecture
/* traitements */
Fermer fic
Fin
2. Lire et écrire des enregistrements
a. Lecture
Pour simple rappel, les enregistrements sont ici les lignes d’un fichier texte, un enregistrement étant équivalent à une ligne. La lecture d’une ligne se fait via l’instruction Lire. Lire lit l’enregistrement présent à la position actuelle du fichier, puis se place sur l’enregistrement suivant. À l’ouverture du fichier, Lire lit la première ligne. Un nouveau Lire lira la deuxième, et ainsi de suite jusqu’à la fin. C’est pour cela que la lecture est dite séquentielle. Vous trouverez aussi la même instruction sous le nom LireFichier, c’est la même...
Les fichiers binaires
1. Nouvelles instructions
L’accès aux fichiers binaires reprend les mêmes principes généraux, sauf qu’il s’agit cette fois d’une suite d’octets, et non d’enregistrements. Il faut donc :
-
Un nouveau mode d’ouverture de fichier : binaire.
-
Une nouvelle fonction prédéfinie de lecture : LireOctet(fic), qui retourne la valeur.
-
Une nouvelle fonction prédéfinie d’écriture : EcrireOctet(fic,valeur).
-
Une fonction prédéfinie pour récupérer l’endroit courant : Position(fic).
-
Une fonction prédéfinie pour aller à un autre endroit : Position(fic,pos).
Les autres instructions et fonctions (Ouvrir, Fermer, EOF) restent valides.
2. Exemple
Voici l’exemple qui permet de lire un fichier octet par octet et d’afficher le caractère ASCII correspondant et la taille du fichier à la fin :
Programme LIREBINAIRE
Var
fic :fichier binaire
octet :entier
Début
Ouvrir nom dans fic en lecture
Tant que NON EOF(fic) Faire
octet←LireOctet(fic)
Afficher Caractere(octet)
FinTantQue
Afficher " Taille du fichier : ", position(fic)
Fermer fic
Fin
En C#, vous n’utiliserez plus StreamReader...
Exercices
Exercice 1
Écrire l’algorithme COPIE qui copie un fichier dans un autre, octet par octet. Donner le programme C# associé.
Exercice 2
Cet exercice représente une synthèse des précédents chapitres et propose de développer un utilitaire complet, pratique et fonctionnel.
Le but de cet exercice est de concevoir un programme capable de lire un fichier octet par octet et d’en afficher la représentation au format hexadécimal à gauche et au format ASCII à droite. Chaque ligne affichera 16 caractères. Un compteur de position sera affiché tout à gauche. Si le caractère n’est pas imprimable, il sera remplacé par un point.
Le format attendu est le suivant :
00000000 23 21 2f 62 69 6e 2f 62 61 73 68 0a 0a 5b 20 24 |#!/bin/bash..[ $|
00000010 23 20 2d 6c 74 20 31 20 5d 20 26 26 20 65 78 69 |# -lt 1 ] && exi|
00000020 74 20 31 3b 0a 0a 74 79 70 65 73 65 74 20 2d 69 |t 1;..typeset -i|
Il s’agit donc de programmer un outil de dump de fichier binaire en hexadécimal. Vous pouvez vous...