Vous êtes sur la page 1sur 10

Apprendre C++ avec Qt : Leon 7

Utiliser des fichiers de donnes


Centre Informatique pour les Lettres
et les Sciences Humaines

1 - La classe QFileDialog ....................................................................................................... 2


2 - La classe QFile................................................................................................................... 2
Dsignation du fichier .....................................................................................................2
Informations disponibles .................................................................................................3
Effacer un fichier.............................................................................................................3
Ouvrir un fichier .............................................................................................................3
Erreurs d'ouverture .........................................................................................................4
Grer la position courante ...............................................................................................5
Fermer un fichier ............................................................................................................5
3 - La classe QTextStream ....................................................................................................... 6
Connexion un fichier ....................................................................................................6
Ecrire ..............................................................................................................................6
Lire .................................................................................................................................7
4 - En pratique......................................................................................................................... 8
Lecture d'un fichier comportant du texte et des donnes numriques..............................8
Transmission d'un fichier une fonction .........................................................................9
Recherche dans le code source d'une erreur qui est dans le fichier de donnes................9
5 - Bon, c'est gentil tout a, mais a fait dj 8 pages. Qu'est-ce que je dois vraiment en
retenir ?............................................................................................................................. 10

Document du 08/01/08

Retrouvez la version la plus rcente sur http://sites.univ-provence.fr/wcpp

C++ - Leon 7

Utiliser des fichiers de donnes

2/10

De nombreux programmes exigent une mthode permettant de leur fournir des donnes
autrement qu'en les tapant au clavier ou en les transfrant depuis une autre application par
copier/coller. Il se peut aussi que les rsultats produits par un programme mritent d'tre
stocks en vue d'un usage ultrieur. La librairie Qt propose plusieurs classes qui facilitent
l'utilisation de fichiers, c'est dire le transfert d'informations entre disques et mmoire.

1 - La classe QFileDialog
Dans bien des cas, c'est l'utilisateur du programme qui doit tre en mesure d'indiquer quel
fichier de donnes il faut utiliser, ou quel fichier doit tre cr pour y stocker les rsultats
obtenus. La classe QFileDialog permet d'offrir l'utilisateur un moyen d'exprimer son choix.
L'utilisation du type QFileDialog implique la prsence d'une directive
#include "QFileDialog.h"
Pour faire dsigner un fichier de donnes, on utilisera la fonction getOpenFileName() :
1

QString chemin = QFileDialog::getOpenFileName();


Sous Windows, l'excution de cette ligne de code fait
apparatre la fentre reprsente ci-contre, et l'excution du
programme est suspendue jusqu' ce que l'utilisateur mette
fin au dialogue.
Si le dialogue s'achve par un clic sur [Ouvrir], la QString
renvoye contient le chemin complet d'accs au fichier
dsign. Dans le cas contraire, elle est vide.
La fonction getSaveFileName() fonctionne de faon analogue, mais le dialogue propos est de
type "Enregistrer sous", ce qui permet l'utilisateur de crer un nouveau fichier.

2 - La classe QFile
La classe QFile permet de mettre en relation le programme et les fichiers de donnes. C'est en
effet une instance de cette classe qu'il faut dsigner le fichier concern, et c'est ensuite en
agissant sur cette variable que le programme pourra, indirectement, manipuler le fichier.
L'utilisation du type QFile implique la prsence d'une directive #include "QFile.h"
Dsignation du fichier
Initialiser une instance de QFile l'aide d'une chane dsignant un fichier permet d'obtenir
une variable associe ce fichier :
2

QFile leFichier(chemin);
La fonction setName() permet de changer le fichier associ une variable de type QFile :

leFichier.setName("unAutre.txt");
Lors de l'initialisation du QFile ou de l'appel de setName(), le fichier peut tre dsign par un
chemin d'accs (complet ou relatif). L'utilisation de la barre oblique '/' permet de dcrire un
chemin valide quel que soit le systme d'exploitation utilis :

leFichier.setName("data/mes_donnees.txt"); //correct, quel que soit l'OS


//sous Windows, on peut aussi crire : leFichier.setName("data\\mes_donnees.txt");
//sous MacOs, on peut aussi crire : leFichier.setName("data:mes_donnees.txt");

Notez bien que setName() ne permet en aucune faon de renommer un fichier. Il s'agit
simplement d'utiliser la mme variable de type QFile pour travailler sur un autre fichier, ce
qui suppose que le fichier prcdemment utilis est en tat d'tre ainsi "abandonn".
Inversement, la fonction name() fournit le nom du fichier auquel un QFile est associ :
5

QString nom = leFichier.name();


J-L Pris - 08/01/08

C++ - Leon 7

Utiliser des fichiers de donnes

3/10

Informations disponibles
Ds lors qu'elle est associe un nom de fichier, une variable de type QFile peut fournir un
certain nombre de renseignements concernant ce fichier.
La fonction exists() renvoie un boolen qui confirme (ou infirme) l'existence du fichier
associ la variable QFile au titre de laquelle elle est invoque :
6
7
8

QString message = "Il n'existe aucun fichier nomm " + leFichier.name();


if(leFichier.exists())
message = leFichier.name() + " existe bel et bien";
La fonction exists() peut galement tre invoque au titre de la classe QFile, condition de
lui passer comme argument le nom du fichier concern :
bool ilEstLa = QFile::exists("monFichier.txt");

La fonction size() renvoie la taille (en octets) du fichier associ la variable QFile au titre de
laquelle elle est invoque :
10

unsigned int tailleFichier = leFichier.size();


Effacer un fichier
La classe QFile permet galement d'effacer du disque un fichier devenu inutile (un fichier
temporaire cr par le programme lui-mme, par exemple).
Attention : l'effacement ainsi obtenu est dfinitif (pas de mise " la poubelle" ou " la corbeille").
C'est la fonction remove() qui assure ces basses uvres, et elle peut tre invoque soit au titre
d'une instance de QFile (11), soit au titre de la classe elle-mme (12). Dans ce dernier cas, il
faut videmment qu'un argument lui dsigne le condamn :

11
12

leFichier.remove();
QFile::remove("temp.txt");
Tournez sept fois votre code source dans votre compilateur avant de commettre un programme
effaant autre chose qu'un fichier temporaire qu'il vient lui-mme de crer...
Ouvrir un fichier
Lorsqu'un programme manipule des fichiers, il s'intresse gnralement leur contenu. Pour
accder, ce contenu, il est ncessaire d'ouvrir le fichier.
L'ouverture d'un fichier ne se traduit pas par l'apparition l'cran d'une fentre contenant un
texte correspondant au contenu de ce fichier. Du point de vue d'un programme, un fichier est
"ouvert" lorsqu'il est prt participer des transferts de donnes entre disque et mmoire.

C'est la fonction open() qui assure l'ouverture du fichier associ la variable QFile au titre de
laquelle elle est invoque. Cette fonction exige un argument qui indique quelles oprations le
fichier doit ensuite se prter. La valeur de cet argument est fixe en utilisant des constantes
prdfinies dans la librairie Qt :
Mode douverture
IO_ReadOnly
IO_WriteOnly
IO_WriteOnly | IO_Append

Oprations autorises par l'ouverture


Lecture du contenu du fichier.
Ecriture dans le fichier, en crasant son contenu antrieur.
Si le fichier n'existe pas encore, il est cr.
Ecriture dans le fichier, la suite de son contenu antrieur
Si le fichier n'existe pas encore, l'ouverture choue.

Typiquement, l'utilisation d'un fichier de donnes donnera donc lieu des squences telles que
1
2

QFile lesDonnees("data.txt");
lesDonnees.open(IO_ReadOnly); //on va LIRE les donnes !

3
4

QFile resultats("rsultats.txt");
resultats.open(IO_WriteOnly); //on va remplacer le contenu du fichier

5
6

QFile journalDeBord("historique.txt");
journalDeBord.open(IO_WriteOnly | IO_Append); //on va crire la fin du fichier
J-L Pris - 08/01/08

C++ - Leon 7

Utiliser des fichiers de donnes

4/10

Ces modes d'ouverture peuvent tre complts l'aide de la constante IO_Translate, d'une
demande de traduction automatique de la reprsentation des marques de paragraphe.
Certains fichiers reprsentent les sauts de paragraphe l'aide de deux caractres conscutifs
("\r\n", c'est dire 0x0D 0x0A) alors que d'autres se contentent d'un seul ('\n'). L'criture de
programmes grant correctement tous les fichiers contenant du texte est facilite par le mode
IO_Translate, qui permet de ne jamais voir apparatre les '\r' qui, dans certains fichiers,
prcdent les '\n'.

Remarquez que la combinaison de plusieurs caractristiques d'ouverture du fichier est obtenue


l'aide de l'oprateur "OU bitaire" :
7
8

QFile leTexte("blabla.txt");
leTexte.open(IO_ReadOnly | IO_Append | IO_Translate);
L'usage des oprateurs bitaires est prsent en dtails dans la Leon 24, qui vous permettra
de comprendre pourquoi la conjonction de deux modes est obtenue l'aide d'un OU et non,
comme on pourrait s'y attendre, l'aide d'un ET.

Erreurs d'ouverture
La fonction open() renvoie un boolen indiquant si tout s'est bien pass.
Tout programme srieux doit grer les cas d'chec d'ouverture des fichiers qu'il utilise.
De nombreuses causes peuvent conduire un tel chec, mme si le fichier existe (l'utilisateur
du programme peut, par exemple, ne pas avoir le droit d'accder au fichier concern).

Lorsqu'un programme ne parvient pas ouvrir un fichier, il devrait, au minimum, prvenir


l'utilisateur en indiquant clairement quel est le fichier incrimin.
Une fonction ouvrant un fichier devrait donc toujours contenir une construction du genre :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

const QString signature = "monProgramme"; //le nom du programme


QString message;
QFile config("config.txt");
if(!config.exists())
{
message = "Le fichier " + config.name() + " n'existe pas";
QMessageBox::critical(0, signature, message);
return;
}
if(!config.open(IO_ReadOnly | IO_Translate))
{
message = "Impossible d'ouvrir le fichier " + config.name();
QMessageBox::critical(0, signature, message);
return;
}
//tout va bien, on peut essayer de lire le contenu du fichier
Les dbutants rechignent frquemment devant la perte de temps que reprsente, selon eux, la
mise en place d'un tel dispositif. Ils s'en dispensent donc, et passent ensuite des heures
essayer de trouver une erreur imaginaire dans le traitement qu'ils ont programm, pour finir
par comprendre que, du fait d'un chec d'ouverture d'un fichier, leur programme manque tout
simplement des donnes ncessaires pour produire le rsultat attendu.
Cette coupable dsinvolture est malheureusement encourage par le fait que, pour des raisons
videntes de gain de place et de lisibilit, les exemples figurant dans les livres ou les cours de
programmation (mme les meilleurs) ne rptent pas systmatiquement les lignes de code
assurant les mesures de scurit lmentaires.
Un exemple de code n'est pas un programme complet et srieux.
Autrement dit : faites ce que je dis, ne faites pas ce que je fais (ici).

J-L Pris - 08/01/08

C++ - Leon 7

Utiliser des fichiers de donnes

5/10

Grer la position courante


Qu'il s'agisse de lecture ou d'criture, les oprations effectues sur un fichier modifient
automatiquement la "position courante", c'est dire l'endroit o dbutera l'opration suivante.
En clair : si vous crivez deux fois de suite dans le mme fichier, la seconde opration n'efface
pas l'effet de la premire mais crit la suite de ce qu'a crit la premire. De mme, deux
lectures conscutives ne donneront pas la mme information, mais deux informations qui,
dans le fichier, sont la suite l'une de l'autre.

La fonction atEnd() renvoie true lorsque la position courante a atteint la fin du fichier. En
d'autres termes, elle renvoie false tant que le fichier contient des donnes non encore lues, et
c'est donc gnralement cette fonction qui est utilise pour organiser la lecture complte d'un
fichier de donnes :
16
17
18

while (! config.atEnd())
{
//extraction des donnes (cf. la suite de cette Leon)
}
La fonction at() renvoie la position courante, exprime en nombre d'octets depuis le dbut du
fichier.
La fonction at() peut aussi tre utilise pour modifier la position courante : il suffit pour cela
de lui passer la position dsire, exprime en nombre d'octets depuis le dbut du fichier.
Utilise ainsi, la fonction at() renvoie un boolen qui indique si le dplacement demand a
bien t effectu.
Deux cas particuliers sont signaler :
- Si la position d'criture est dplace au-del du dernier caractre actuel, la fonction at()
insre automatiquement des octets nuls dans le no man's land ainsi cr, mais ces octets ne
sont effectivement ajouts au fichier que si une opration d'criture est ensuite effectue.
- Lorsqu'un fichier a t ouvert en mode IO_WriteOnly | IO_Append, toutes les critures
s'effectuent en fin de fichier, mme si la position courante a t pralablement dplace.
Le dplacement explicite de la position courante est une manuvre qui doit tre effectue avec
circonspection, surtout lorsque le fichier concern est ouvert en criture.
Une erreur de programmation peut, dans ce cas, se traduire par un crasement de donnes

Fermer un fichier
Une fois son utilisation termine, un fichier peut tre referm en appelant la fonction close()
au titre de la variable de type QFile qui lui est associe. La squence d'instructions prenant
place entre les lignes 17 et 18 du fragment de code prcdent pourrait donc se terminer par :
config.close();
Une fois referm, le fichier ne se prte plus aucune opration de lecture ou d'criture, et la
variable de type QFile qui servait le manipuler peut en toute scurit tre associe un
autre fichier ( l'aide de la fonction setName() prsente prcdemment).
La disparition de la variable de type QFile (pour cause de fin du bloc dans lequel elle est
dfinie, par exemple) assure galement la fermeture du fichier correspondant, sans qu'il soit
besoin d'appeler la fonction close().

Bien entendu, avant de refermer un fichier, le programme aura vraisemblablement besoin de


l'utiliser pour en lire le contenu ou pour y placer ses rsultats. Dans la plupart des cas,
toutefois, ces oprations ne se font pas en utilisant directement la variable de type QFile
associe au fichier, mais en passant par l'intermdiaire d'une variable de type QTextStream.

J-L Pris - 08/01/08

C++ - Leon 7

Utiliser des fichiers de donnes

6/10

3 - La classe QTextStream
Bien qu'elle soit ici dcrite dans le contexte de l'accs des fichiers de donnes, la classe
QTextStream est capable de fournir les mmes services dans d'autres contextes, ce qui justifie
qu'elle ait une existence indpendante de la classe QFile.
La classe QTextStream peut ainsi servir lire/crire des donnes dans une simple QString
ou faire communiquer deux ordinateurs connects par leur port srie.

L'utilisation du type QTextStream implique la prsence d'une directive


#include "QTextStream.h"
Connexion un fichier
L'initialisation d'une variable de type QTextStream avec l'adresse d'une instance de QFile
permet d'obtenir la connexion du QTextStream au fichier associ au QFile. Les oprations de
lecture ou d'criture portant sur le QTextStream se traduiront donc par un transfert
d'information depuis ou vers ce fichier.
1
2
3

QFile leFichier ("unFichier.txt");


leFichier.open(IO_WriteOnly | IO_Translate);
QTextStream destination(& leFichier);
Lorsqu'une variable de type QTextStream est connecte un fichier, cette connexion peut tre
rompue en appelant la fonction unsetDevice() :

destination.unsetDevice();
Un QTextStream peut tre connect un nouveau fichier l'aide de la fonction setDevice(),
laquelle il faut passer l'adresse d'un QFile associ au fichier concern :

5
6
7

QFile unAutre("unAutreFichier.txt");
unAutre.open(IO_WriteOnly | IO_Translate);
destination.setDevice(& unAutre);
Ecrire
Lorsqu'un QTextStream est connect un fichier ouvert en criture, l'oprateur d'insertion,
permet de placer dans ce fichier la squence de caractres reprsentant la valeur sur laquelle
est appliqu l'oprateur. Le fragment de code suivant place donc dans le fichier nomm
"unAutreFichier.txt" les caractres '0', '1', '2', '3', '4', '5', spars par des passages la ligne :

8
9
10

int n;
for (n = 0 ; n < 6 ; n = n + 1)
destination << n << "\n";
Si vous avez fait les exercices proposs dans le TD 4, l'oprateur << devrait vous paratre
familier. La "magie noire" pratique dans ce TD a en effet pour but de vous permettre d'crire
l'cran exactement comme on crit dans un fichier lorsqu'on utilise un QTextStream.

Tous les types prdfinis (int, double, etc.), ainsi que les classes Qt pour lesquelles cela un
sens (QString, par exemple) acceptent de voir leurs instances ainsi "injectes" dans un
QTextStream. Pour ce qui est des classes que nous dfinirons nous-mmes, il nous
appartiendra de les doter de cette caractristique (cf. Leon 11).
Notez que les boolens true et false, lorsqu'ils sont insrs dans un QTextStream, sont
respectivement reprsents par les caractres '1' et '0', et non par les chanes "true" et "false".
Il faut aussi savoir que l'insertion de donnes dans un QTextStream ne se traduit pas
toujours immdiatement par l'criture de ces donnes dans le fichier. Pour amliorer la
vitesse d'excution, le systme garde en effet les donnes en mmoire en attendant d'en avoir
suffisamment pour justifier un accs au disque concern (cette opration est relativement
longue et sa dure n'est pas directement proportionnelle au volume de donnes transfrer).
Si un programme doit faire en sorte que les donnes en attente soit effectivement crites sur
le disque un moment donn, il peut faire appel la fonction QFile::flush() :
leFichier.flush();

J-L Pris - 08/01/08

C++ - Leon 7

Utiliser des fichiers de donnes

7/10

Remarquez que la fonction flush() doit tre invoque au titre du QFile, et non au titre du
QTextStream qui lui est associ. Bien entendu, la fermeture du fichier (par close() ou par
disparition de la variable de type QFile utilise) garantit aussi que toutes les donnes en
attente sont physiquement crites sur le disque.

Lire
Lorsqu'un QTextStream est connect un fichier ouvert en lecture, l'oprateur d'extraction
not >>, permet de placer dans la variable sur laquelle il est appliqu une valeur construite
partir d'une suite de caractres lus dans le fichier.
Il s'agit d'une simple opration de lecture : contrairement ce que le terme "extraction"
pourrait laisser croire, le contenu du fichier n'est nullement modifi.

La suite de caractres utilise pour construire la valeur attribue la variable s'arrte ds


qu'un caractre non interprtable dans ce contexte est rencontr. Ainsi, si un fichier contient
124.32abc
et qu'il est lu au moyen d'un QTextStream nomm source, on aura :
1
2
3
4

double x;
source >> x;
QString texte;
source >> texte;

//x reoit la valeur 124.32


//texte reoit la valeur "abc"

Comme le caractre '.' ne peut pas figurer dans la reprsentation d'une valeur entire, la
lecture du mme fichier donnera lieu une interprtation diffrente si on crit :
1
2
3
4

int a;
source >> a;
QString texte;
source >> texte;

//a reoit la valeur 124


//texte reoit la valeur ".32abc"

Les caractres dits "sparateurs" (espace, tabulation, saut de ligne) sont considrs comme
n'tant interprtables dans aucun contexte, c'est dire qu'ils mettent fin la suite de
caractres utilise pour construire la valeur lue, quel que soit le type de la variable dans
laquelle cette valeur va tre stocke. Ainsi, si notre fichier contient
TOTO 999
nous aurons :
1
2
3
4

QString texte;
source >> texte;
int a;
source >> a;

//texte reoit la valeur "TOTO"


//a reoit la valeur 999

Lorsqu'un fichier contient du texte "ordinaire" (ie. une suite de mots formant des phrases), sa
lecture au moyen de l'oprateur d'extraction ne permet donc que d'obtenir les "mots" un par
un, sans indication sur la nature du caractre qui les sparait (un espace ? un saut de ligne ?).
Cette faon de lire le fichier ne convient donc pas toutes les situations, et la classe
QTextStream offre d'autres possibilits.
La fonction readLine() renvoie une QString qui contient tous les caractres compris entre la
position de lecture courante et le saut de ligne suivant.
Notez que le saut de ligne ne figure pas la fin de la QString. Cette faon de lire est trs
adapte aux cas des fichiers composs de "paragraphes", comme par exemple lorsqu'il s'agit
d'une liste comportant un item par ligne.

La fonction read() renvoie une QString qui contient tous les caractres compris entre la
position courante de lecture du fichier et la fin de celui-ci.
Cette faon de lire convient donc trs bien aux fichiers de taille relativement modre et dans
lesquels les paragraphes n'ont pas une importance fondamentale. Le texte d'un roman, par
exemple, pourra tout fait tre lu de cette faon, qu'il s'agisse de l'afficher l'cran ou d'y
rechercher des phnomnes particuliers.

J-L Pris - 08/01/08

C++ - Leon 7

Utiliser des fichiers de donnes

8/10

La fonction atEnd() (analogue celle disponible dans la classe QFile) permet de dtecter
lpuisement des donnes rendues accessibles par le QTextStream. Cette fonction permet donc
de lire intgralement un fichier dont on ignore la longueur.
Le fragment de code suivant, par exemple, calcule la moyenne des valeurs contenues dans le
fichier "donnes.txt", quel que soit le nombre de celles-ci :
1
2
3
4
5
6
7
8
9
10
11
12
13

QFile leFichier("donnes.txt");
leFichier.open(IO_ReadOnly | IO_Translate);
QTextStream source(&leFichier);
double somme = 0;
int nbValeurs = 0;
double valeurLue;
while(!source.atEnd()) //tant qu'il reste des donnes
{
source >> valeurLue;
somme += valeurLue;
++nbValeurs;
}
double moyenne = somme / nbValeurs;

4 - En pratique
Si les principes en sont simples (il s'agit essentiellement de mettre en place un QFile et un
QTextStream), les fonctions de gestion des fichiers restent souvent la partie du programme
dont la mise au point s'avre la plus laborieuse. Trois difficults mritent d'tre signales.
Lecture d'un fichier comportant du texte et des donnes numriques
Comme nous l'avons vu, l'oprateur d'extraction considre que la donne qu'il est charg de
lire s'arrte au premier caractre "non interprtable" tant donn le type de valeur qu'il cherche
lire. Ce caractre "non interprtable" n'est pas extrait du fichier et reste disponible pour
l'opration de lecture suivante.
Dans notre exemple o le fichier contient
124.32abc
sa lecture par
double x;
fichier >> x;
//x reoit la valeur 124.32
QString texte;
fichier >> texte;
//texte reoit la valeur "abc"
fait intervenir deux fois le 7 caractre du fichier : il indique dans un premier temps que la
squence de caractres dcrivant la valeur dcimale est termine, et il est ensuite le premier
caractre plac dans la QString.

Comme l'oprateur d'extraction considre que les "sparateurs" ne sont jamais interprtables,
son usage est peu pratique lorsqu'il s'agit de lire un fragment de texte susceptible de contenir
des espaces (un chemin d'accs un fichier du genre "c:/Mes Documents/", par exemple, ou
un nom propre comme "du Pont"). Dans ce genre de cas, on prfre souvent extraire le texte en
appelant la fonction readLine() qui, comme son nom l'indique, lit jusqu' la fin de la ligne. Le
dfaut de readLine() est qu'elle renvoie une QString qui, dans le cas des donnes
numriques, doit tre convertie pour devenir utilisable. Face un fichier dont certaines lignes
contiennent du "vrai" texte alors que d'autres doivent tre interprtes comme des valeurs
numriques, il est donc tentant d'utiliser readline() pour les unes et l'oprateur d'extraction
pour les autres. Applique navement, cette mthode ne fonctionne malheureusement pas.
Considrons un fichier dont le contenu est le suivant :
178.56
Aix en Provence
Essayer d'extraire les donnes l'aide de la squence
double valeurNumerique;
source >> valeurNumerique;
QString nomDeLaVille = source.readLine(); //nomDeLaVille reste vide !
J-L Pris - 08/01/08

C++ - Leon 7

Utiliser des fichiers de donnes

9/10

ne donne pas le rsultat attendu. Le "caractre non interprtable" qui met fin l'extraction de
la valeurNumrique est en effet le caractre de fin de ligne. Il reste donc disponible pour
l'opration de lecture suivante qui, dans ce cas, utilise readLine(). Puisque les donnes
restant lire commencent par un caractre de fin de ligne, cette fonction renvoie videmment
une chane vide Une premire solution consiste utiliser systmatiquement readLine() :
QString ligne = source.readLine();
double valeurNumerique = ligne.toDouble();
QString nomDeLaVille = source.readLine();

//lecture de "178.56"
//calcul de la valeur 178.56
//lecture de "Aix en Provence"

Une autre mthode, parfois plus agrable, est d'utiliser la fonction skipWhiteSpace() :
double valeurNumerique;
source >> valeurNumerique;
source.skipWhiteSpace();
//extraction du passage la ligne
QString nomDeLaVille = source.readLine(); //lecture de "Aix en Provence"
Transmission d'un fichier une fonction
Du fait mme de leur rle, les instances des classes QFile et QTextStream doivent contenir
des pointeurs leur permettant d'accder l'objet auquel elles sont associes (un fichier dans le
cas des QFile, un QFile dans le cas des QTextStream). Lorsque la valeur d'une instance est
attribue une autre instance, ces pointeurs sont copis, et les deux instances se retrouvent
associes au mme objet.
Outre les incohrences que ceci risque d'entraner (si le mme objet est manipul tantt via
une instance, tantt via l'autre), cette situation cre un problme lors de la disparition des
instances qui ont t copies l'une sur l'autre. La premire d'entre elles qui disparat provoque
en effet un "grand nettoyage" qui rend invalides les pointeurs contenus dans l'autre instance.
Mme si celle-ci n'est pas utilise, sa disparition provoquera immanquablement une erreur
d'excution lorsqu'un second "grand nettoyage" sera entrepris sur des objets qui, du fait du
premier, n'existent plus. Les deux instructions suivantes, par exemple, suffisent gnrer une
erreur d'excution (ie. un "plantage" du programme) :
QFile un;
QFile deux = un; //HORREUR ! Copie d'un QFile !
On peut s'interroger sur la logique qui conduirait placer de telles instructions dans un
programme, mais il existe bien d'autres situations conduisant copier la valeur d'un objet
dans un autre. Une de ces situations est l'initialisation d'un paramtre avec la valeur
transmise par la fonction appelante. Par consquent :
Un paramtre de ne doit jamais tre de type QFile ou QTextStream. Utilisez un pointeur ou
une rfrence pour donner aux fonctions qui en ont besoin accs aux objets de ce type.
Comme vous le savez, la transmission de l'adresse d'un objet ne ncessite aucune recopie de
cet objet, la fonction travaillant sur l'original (auquel elle accde en drfrenant le pointeur
qui contient cette adresse). De faon similaire, un paramtre "rfrence" sera associ l'objet
original, sans qu'aucune copie ne soit effectue.

Recherche dans le code source d'une erreur qui est dans le fichier de donnes
Si la mise au point du code grant les fichiers de donnes est souvent laborieuse, c'est en
particulier parce que les programmeurs dbutants perdent beaucoup de temps essayer de
corriger des programmes parfaitement corrects.
Avant de tester votre programme, vrifiez que les fichiers de donnes qu'il va utiliser sont bien
structurs comme prvu. Une simple ligne vide inattendue peut avoir pour effet de dcaler les
donnes, ce qui donne parfois l'impression (trs dcourageante) que tout le programme est
inepte et doit tre r-crit en partant de zro.
Dans un programme idal, chaque acquisition de donnes devrait immdiatement faire l'objet
de vrifications de cohrence donnant lieu, en cas de besoin, des messages de diagnostic
circonstancis. En ralit, la mise en place de ces diagnostics exige un effort qui ne se justifie
que pour des programmes qui vont rencontrer d'autres utilisateurs que leur auteur, et il est
vraisemblable que vos premiers projets devront s'en passer.
J-L Pris - 08/01/08

C++ - Leon 7

Utiliser des fichiers de donnes

10/10

5 - Bon, c'est gentil tout a, mais a fait dj 8 pages. Qu'est-ce que


je dois vraiment en retenir ?
1) Pour manipuler un fichier (vrifier s'il existe, connatre sa taille, l'effacer, l'ouvrir) on cre
une instance de la classe QFile et on l'initialise avec le nom du fichier.
2) Tout fichier .h ou .cpp qui contient le mot QFile doit comporter une directive
#include "QFile.h"
3) Pour manipuler le contenu d'un fichier, on cre gnralement une instance de la classe
QTextStream que l'on initialise avec le QFile associ au fichier.
4) Tout fichier .h ou .cpp qui contient le mot QTextStream doit comporter une directive
#include "QTextStream.h"
5) Ds qu'un programme utilise des fichiers de donnes, les risques qu'un incident l'empche
de fonctionner normalement cessent d'tre ngligeables. Il doit donc tre conu de faon
ragir correctement en cas d'anomalie.
6) On crit dans un QTextStream en utilisant l'oprateur d'insertion.
7) On lit un QTextStream soit en utilisant l'oprateur d'extraction, soit en utilisant les
fonctions readLine() ou read().
8) L'oprateur d'extraction n'extrait pas le caractre qui suit la fin de la donne lue. Si ce
caractre est un saut de ligne et que la lecture suivante est faite par readLine(), cette
fonction va interprter ce saut de ligne comme la fin des donnes qu'elle doit lire et renvoyer
une chane vide. Il faut, dans ce cas, utiliser skipWhiteSpace() pour franchir l'obstacle.
9) Aucun paramtre ne doit tre de type QFile ou QTextStream. Utilisez des pointeurs ou des
rfrences.

J-L Pris - 08/01/08

Vous aimerez peut-être aussi