programmez-en-d/fichiers.whata

178 lines
9.0 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[set
title = "Fichiers"
partAs = chapitre
translator = "Raphaël Jakse"
proofreader = "Stéphane Goujet"
]
Nous avons vu dans le chapitre précédent que les flux d'entrée et de sortie standard peuvent être redirigés vers et depuis des fichiers ou d'autres programmes avec les opérateurs [c > >], [c < ] et [c > | ] dans la console. Malgré leur puissance, ces outils ne sont pas adaptés dans toutes les situations parce que dans beaucoup de cas, les programmes ne peuvent pas effectuer leurs tâches en lisant leur entrée et en écrivant sur leur sortie.
Par exemple, un programme qui gère des enregistrements d'étudiants pourrait utiliser sa sortie standard pour afficher le menu du programme. Mais un tel programme aurait besoin d'écrire les enregistrements dans un fichier plutôt que dans [c stdout].
Dans ce chapitre, nous allons voir comment lire et écrire des fichiers du système de fichiers.
[ = Concepts fondamentaux
Les fichiers sont représentés par la structure [c File] du module [c std.stdio]. Comme je n'ai pas encore présenté les structures, il faudra accepter leur syntaxe telle quelle.
Avant de rentrer dans le code, il faut voir les idées fondamentales à propos des fichiers.
[ = Le producteur et le consommateur
Les fichiers qui sont créés sur une plateforme peuvent ne pas être utilisables tels quels sur d'autres plateformes. Simplement ouvrir un fichier et écrire des données dedans peut ne pas être suffisant pour que ces données soient disponibles au consommateur. Le producteur et le consommateur des données doivent d'abord se mettre d'accord sur le format des données qui sont dans le fichier. Par exemple, si le producteur a écrit l'identifiant et le nom des enregistrements des étudiants dans un certain ordre, le consommateur doit lire les données dans le même ordre.
De plus, les exemples de code ci-après n'écrivent pas de BOM au début du fichier. Ceci peut rendre vos fichiers incompatibles avec les systèmes qui nécessite une BOM (BOM veut dire ''Byte Ordrer Mark'', [[wiki:fr Byte_Order_Mark | indicateur d'ordre des octets]]).
]
[ = Droits d'accès
Les systèmes de fichiers donnent accès aux fichiers aux programmes avec certains droits. Les droits d'accès sont aussi important pour l'intégrité des données que pour les performances.
Quand il s'agit de lire, autoriser plusieurs programmes à lire depuis le même fichier améliore les performances parce qu'aucun programme n'a à attendre que les autres finissent leur lecture. En revanche, quand il s'agit d'écrire, un seul programme devrait être autorisé à écrire dans un fichier donné, sinon les programmes pourraient remplacer les données des autres programmes.
]
[ = Ouvrir un fichier
Les flux d'entrée et de sortie standard [c stdin] et [c stdout] sont déjà [* ouverts] quand les programmes démarrent. Ils sont prêts à être utilisés.
En revanche, les fichiers doivent d'abord être ouverts en indiquant leur nom et les droits d'accès nécessaires.
]
[ = Fermer un fichier
Tout fichier qui a été ouvert par un programme doit être fermé quand le programme a fini de l'utiliser. Dans la plupart des cas, les fichiers n'ont pas besoin d'être fermés explicitement, ils sont fermés automatiquement quand les objets [c File] sont détruits automatiquement~ :
[code=d <<<
if (uneCondition) {
// On suppose qu'un objet File a été créé et utilisé ici.
// ...
} // ← Le fichier sera fermé automatiquement ici en sortie
// de la structure if. Pas besoin de le fermer explicitement.
>>>]
Dans certains cas, il peut être nécessaire qu'un objet [c File] soit ré-ouvert pour accéder à un fichier différent ou au même fichier avec des droits d'accès différents. Dans de tels cas, le fichier doit être fermé et ensuite ré-ouvert~ :
[code=d <<<
fichier.close();
fichier.open("enregistrements_etudiants", "r");
>>>]
]
[ = Écrire et lire un fichier
Comme les fichiers sont des flux de caractères, les fonctions d'entrée et de sortie [c writeln], [c readf], etc. sont utilisées exactement de la même manière avec eux. La seule différence est que le nom de la variable [c File] suivie d'un point doivent être ajoutés~ :
[code=d <<<
writeln("bonjour"); // écrit sur la sortie standard
stdout.writeln("bonjour"); // même chose que la ligne précédente
fichier.writeln("bonjour"); // écrit dans un fichier spécifique
>>>]
]
[ = [c eof()] pour tester la fin du fichier
La méthode [c eof()] détermine si la fin du fichier a été atteinte pendant la lecture du fichier. Quand c'est le cas, elle retourne [c true].
Par exemple, la boucle suivante sera exécutée jusqu'à la fin du fichier~ :
[code=d <<<
while (!fichier.eof()) {
/* ... */
}
>>>]
]
[ = Le module [c std.file]
Le [[ http://dlang.org/phobos/std_file.html | module [c std.file]]] contient des fonctions et des types qui sont utiles pour travailler avec le contenu des dossiers. Par exemple, la fonction [c exists] peut être utilisée pour savoir si un fichier ou un dossier existe sur le système de fichier :
[code=d <<<
import std.file;
// ...
if (exists(nomFichier)) {
// Il y a un fichier ou un dossier qui porte ce nom
} else {
// Aucun fichier ou dossier portant ce nom
}
>>>]
]
]
[ = La structure [c std.stdio.File]
[c File] utilise les mêmes caractères de mode que ceux qui sont utilisés par la fonction [c fopen] du langage C.
|= Mode |= Definition |
|[c r] | Accès en lecture. Le fichier est ouvert et lu depuis le début. |
|[c r+] | Accès en lecture et en écriture. Le fichier est ouvert pour être lu et écrit depuis le début. |
|[c w] | Accès en écriture. Si le fichier n'existe pas, un fichier vide est créé. S'il existe déjà, son contenu est écrasé. |
|[c w+] | Accès en lecture et en écriture. Si le fichier n'existe pas, un fichier vide est créé. S'il existe déjà, son contenu est écrasé.|
|[c a] | Accès en ajout. Si le fichier n'existe pas, un fichier vide est créé. Si le fichier existe déjà, son contenu est conservé. Les données seront écrite à la fin du fichier.|
|[c a+] | Accès en lecture et en ajout. Si le fichier n'existe pas, un fichier vide est créé. Si le fichier existe déjà, son contenu est conservé et le fichier est ouvert pour être lu au début et écrit à la fin.|
Un caractère [c 'b'] peut être ajouté à la chaîne de mode, comme dans [c "rb"]. Ceci peut avoir un effet sur les plateformes qui supportent le [* mode binaire], mais il est ignoré sur tous les systèmes POSIX.
La structure [c File] est comprise dans le module [[http://dlang.org/phobos/std_stdio.html | [c std.stdio]]].
]
[ = Écrire dans un fichier
Le fichier doit avoir été ouvert dans un des modes d'écriture~ :
[code=d <<<
void main()
{
File fichier = File("enregistrements_etudiants", "w");
fichier.writeln("Nom : ", "Zafer");
fichier.writeln("Numéro : ", 123);
fichier.writeln("Classe : ", "1A");
}
>>>]
Comme vous devez vous rappeler depuis le [[part:chaines | chapitre sur les chaînes], le type des littéraux tels que [c "enregistrements_etudiants"] est [c string], qui consiste en une suite de caractères immuables. Pour cette raison, il n'est pas possible de construire des objets [c File] à partir d'un nom mutable (par exemple [c char~[~]]).
Le programme ci-dessus crée ou remplace le contenu d'un fichier nommé [c enregistrements_etudiants] dans le dossier dans lequel il a été lancé (le [* dossier de travail] du programme).
[p Note~ : |
Les noms de fichiers peuvent contenir n'importe quel caractère autorisé par le système de fichier. Pour être portable, je n'utiliserai que des caractères ASCII.
]
]
[ = Lire un fichier
Le fichier doit avoir été ouvert dans un des modes de lecture~ :
[code=d <<<
import std.stdio;
import std.string;
void main()
{
File fichier = File("enregistrements_etudiants", "r");
while (!fichier.eof()) {
string ligne = chomp(fichier.readln());
writeln("ligne lue -> |", ligne);
}
}
>>>]
Le programme ci-dessus lit toutes les lignes du fichier nommé [c enregistrements_etudiants] et affiche ces lignes dans la sortie standard.
]
[ = Exercice
Écrire un programme qui demande un nom de fichier à l'utilisateur, ouvre ce fichier, et écrit toutes les lignes non vides de ce fichier dans un autre fichier. Le nom du nouveau fichier peut être basé sur le nom du fichier original. Par exemple, si le nom du fichier original est [c foo.txt], le nouveau fichier peut être appelé [c foo.txt.out].
[[part:corrections/fichiers | … La solution]]
]