La première chose à faire quand on veut manipuler des fichiers, c'est de les ouvrir.

Et bien en C++, c'est la même chose.
Une fois le fichier ouvert, tout se passe comme pour
cout et
cin. Nous allons, par exemple, retrouver les chevrons
<< et
>>. Faites-moi confiance, vous allez rapidement vous y retrouver.
On parle de
flux pour désigner les moyens de communication d'un programme avec l'extérieur. Dans ce chapitre, nous allons donc parler des
flux vers les fichiers. Mais dites simplement "lire et écrire des fichiers" quand vous n'êtes pas dans une soirée de programmeurs.
L'en-tête fstream
Comme d'habitude en C++, quand on a besoin d'une fonctionnalité, il faut commencer par inclure le bon fichier d'en-tête. Pour les fichiers, il faut spécifier
#include <fstream> en-haut de notre code source.
Vous connaissez déjà iostream qui contient les outils nécessaires aux entrées/sorties vers la console. iostream signifie en réalité "input/output stream", ce qui veut dire flux d'entrées/sorties en français. fstream correspond à "file stream", flux vers les fichiers en bon français.
La principale différence est qu'il faut un
flux par fichier. Voyons comment créer un flux sortant, c'est-à-dire un flux permettant d'écrire un fichier.
Ouvrir un fichier en écriture
Les flux sont en réalité des
objets. Souvenez-vous que le C++ est un langage
orienté objet. Voici donc un de ces fameux objets.
N'ayez pas peur, il y aura plusieurs chapitres pour en parler. Pour l'instant, prenez-ça comme étant des grosses variables améliorées. Ces objets contiennent beaucoup d'informations sur les fichiers ouverts et proposent quelques fonctionnalités comme fermer le fichier, retourner au début et bien d'autres encore.
L'important pour nous est que l'on déclare un flux exactement de la même manière qu'une variable. Une variable dont le type serait
ofstream et dont la valeur serait le chemin d'accès du fichier à lire.
Code : C++ - Déclaration d'un flux sortant | #include <iostream>
#include <fstream>
using namespace std;
int main()
{
ofstream monFlux("C:/Nanoc/scores.txt"); //Déclaration d'un flux permettant d'écrire dans le fichier
// C:/Nanoc/scores.txt
return 0;
}
|
J'ai indiqué le chemin d'accès du fichier entre guillemets. Ce chemin doit être d'une des deux formes suivantes :
- Un chemin absolu. C'est-à-dire montrer l'emplacement du fichier depuis la racine du disque. Par exemple : C:/Nanoc/C++/Fichiers/scores.txt.
- Un chemin relatif. C'est-à-dire montrer l'emplacement du fichier depuis l'endroit où se situe le programme sur le disque. Par exemple : Fichiers/scores.txt si mon programme se situe dans le dossier C:/Nanoc/C++/.
A partir de là, on peut utiliser le flux pour écrire dans le fichier.
Si le fichier n'existait pas, le programme le créerait automatiquement !
Le plus souvent, le nom du fichier est contenu dans une chaîne de caractères
string. Dans ce cas, il faut utiliser la fonction
c_str() lors de l'ouverture du fichier.
Code : C++ - Ouverture d'un fichier | string const nomFichier("C:/Nanoc/scores.txt");
ofstream monFlux(nomFichier.c_str()); //Déclaration d'un flux permettant d'écrire un fichier.
|
Des problèmes peuvent survenir lors de l'ouverture d'un fichier. Si le fichier ne vous appartient pas ou si le disque dur est plein par exemple. C'est pour ça qu'il faut
toujours tester si tout s'est bien passé. Cela se fait en utilisant la syntaxe
if(monFlux). Si ce test n'est pas vrai, alors c'est qu'il y a eu un problème et que l'on ne peut pas utiliser le fichier.
Code : C++ - Tester l'ouverture | ofstream monFlux("C:/Nanoc/scores.txt"); //On essaye d'ouvrir le fichier
if(monFlux) //On teste si tout est OK.
{
//Tout est OK. On peut utiliser le fichier
}
else
{
cout << "ERREUR: Impossible d'ouvrir le fichier." << endl;
}
|
Tout est donc prêt pour l'écriture. Et vous allez voir que ce n'est pas vraiment nouveau.
Écrire dans un flux
Je vous avais dit que tout était comme pour
cout. C'est donc sans surprise que je vous présente le moyen d'envoyer des informations dans un flux. C'est les chevrons (
<<) qu'il faut utiliser.
Code : C++ - Écriture dans un fichier 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 | #include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
string const nomFichier("C:/Nanoc/scores.txt");
ofstream monFlux(nomFichier.c_str());
if(monFlux)
{
monFlux << "Bonjour, je suis une phrase écrite dans un fichier." << endl;
monFlux << 42.1337 << endl;
int age(23);
monFlux << "J'ai " << age << " ans." << endl;
}
else
{
cout << "ERREUR: Impossible d'ouvrir le fichier." << endl;
}
return 0;
}
|
Si j'exécute ce programme, je retrouve ensuite sur mon disque un fichier
scores.txt dont voici le contenu :
Essayez par vous-mêmes !
Vous pouvez par exemple écrire un programme qui demande son nom et son âge à l'utilisateur et qui écrit ces données dans un fichier.
Les différents modes d'ouverture
Il ne nous reste plus qu'un petit point à régler.
Que se passe-t-il si le fichier existe déjà ?
Il sera supprimé et remplacé par ce que vous écrivez, ce qui n'est pas bien si l'on souhaite ajouter des informations à la fin d'un fichier pré-existant. Pensez par exemple à un fichier qui contiendrait la liste des actions effectuées par l'utilisateur. On ne veut pas tout effacer à chaque fois. On veut juste y ajouter des lignes.
Pour pouvoir écrire à la fin d'un fichier, il faut le spécifier lors de l'ouverture en ajoutant un deuxième paramètre lors de la création du flux :
ofstream monFlux("C:/Nanoc/scores.txt", ios::app);
app est un raccourci pour append, le verbe anglais qui signifie "ajouter à la fin".
Avec ça, plus de problème d'écrasement des données. Tout ce qui sera écrit sera ajouté à la fin.