'>

Entrée / Sortie avec les fichiers en C_Plus_Plus

C + + fournit les classes suivantes pour exécuter la sortie et l'entrée de caractères de / vers des fichiers:

    ofstream: classe Stream pour écrire sur les fichiers
    ifstreamet: classe Stream pour lire des fichiers
    fstream: classe Stream pour lire et écrire à partir de / vers des fichiers.


Ces classes sont dérivées directement ou indirectement de l'istream classes, et ostream. Nous avons déjà utilisé des objets dont les types sont ces classes: cin est un objet de classe istream et cout est un objet de la classe ostream. Par conséquent, nous avons déjà eu recours à des cours qui sont liés à nos flux de fichiers. Et en fait, nous pouvons utiliser nos flux de fichiers de la même façon que nous sommes déjà habitués à utiliser cin et cout, avec la seule différence que nous devons associer ces flux avec les fichiers physiques. Voyons un exemple:



   

 // basic file operations #include <iostream> #include <fstream> using namespace std; int main () { ofstream myfile; myfile.open ( "example.txt" ); myfile << "Writing this to a file.\n" ; myfile.close(); return 0; }

   

  [Fichier example.txt]
  Écriture à un fichier.



Ce code crée un fichier appelé example.txt et insère une phrase en elle de la même façon que nous sommes habitués à voir avec le cout, mais en utilisant le flux de fichier monfichier place.

Mais allons-y étape par étape:

Ouvrir un fichier

La première opération généralement effectuée sur un objet de l'une de ces classes est de l'associer à un fichier réel. Cette procédure est connue sous le nom pour ouvrir un fichier. Un fichier ouvert est représenté au sein d'un programme par un objet de flux (une instanciation d'une de ces classes, dans l'exemple précédent c'était monfichier) et toute opération d'entrée ou de sortie effectué sur cet objet de flux sera appliquée au fichier physique qui lui est associé .

Pour ouvrir un fichier avec un objet flux, nous utilisons la fonction d'ouverture de membre ():

open (filename, mode);

Où fichier est une séquence de caractères à zéro terminal de Type const char * (du même type que les littéraux chaîne ont) représentant le nom du fichier à ouvrir, et le mode est un paramètre facultatif avec une combinaison des drapeaux suivants:

ios :: dans     Ouvert pour les opérations d'entrée.
ios :: out     Ouvert pour les opérations de sortie.
ios :: binary     Ouvrir en mode binaire.
ios :: mangé     Ensemble de la position initiale à la fin de l'image.
Si cette option n'est pas une valeur quelconque, la position initiale est le début du fichier.
ios :: app     Toutes les opérations de sortie sont réalisées à la fin du fichier, à ajouter le contenu au contenu actuel de l'image. Cet indicateur ne peut être utilisé dans les flux ouverts pour la sortie uniquement les opérations.
ios :: trunc     Si le fichier ouvert pour des opérations de sortie existaient déjà avant, son contenu précédent est supprimé et remplacé par le nouveau.

Tous ces indicateurs peuvent être combinées en utilisant l'opérateur OU binaire (|). Par exemple, si nous voulons ouvrir le fichier example.bin en mode binaire pour ajouter des données Nous pourrions le faire par le recours à la fonction membre open ():


   

 ofstream myfile; myfile.open ( "example.bin" , ios::out | ios::app | ios::binary);



Chacune des fonctions de membre Open () de la ofstream classes, ifstreamet fstream dispose d'un mode par défaut qui est utilisé si le fichier est ouvert sans second argument:

classe     paramètre de mode par défaut,
ofstream     ios :: out
ifstreamet     ios :: dans
fstream     ios :: en | ios :: out

Pour ifstreamet cours ofstream, ios :: dans et ios :: out sont automatiquement et respectivement assumé, même si un mode qui ne comprennent pas leur est passé comme second argument de la fonction membre open ().

La valeur par défaut est appliquée uniquement si la fonction est appelée sans spécifier de valeur pour le paramètre de mode. Si la fonction est appelée avec une valeur dans ce paramètre du mode par défaut est surchargée, non combinés.

Les flux de fichiers ouverts en mode binaire effectuer opérations d'entrée et de sortie indépendamment de toute considération de format. Les fichiers non binaires sont connus comme des fichiers texte, et certaines traductions peuvent se produire en raison du formatage de certains caractères spéciaux (comme les caractères de nouvelle ligne et retour chariot).

Depuis la première tâche qui est effectuée sur un objet de flux de fichier est généralement d'ouvrir un fichier, ces trois classes comprennent un constructeur qui appelle automatiquement la fonction membre open () et a les mêmes paramètres exacts que ce membre. Par conséquent, nous aurions pu également déclaré l'objet monfichier précédent et a mené la même opération d'ouverture dans notre exemple précédent en écrivant:



   

 ofstream myfile ( "example.bin" , ios::out | ios::app | ios::binary);



La combinaison de la construction de l'objet et de l'ouverture des cours d'eau en une seule déclaration. Les deux formes d'ouvrir un fichier sont valides et équivalentes.

Pour vérifier si un flux de fichier a réussi à ouvrir un fichier, vous pouvez le faire en appelant à un membre is_open () sans arguments. Cette fonction membre retourne une valeur bool de vrai dans le cas qui fait l'objet de flux est associé à un fichier ouvert, ou faux sinon:



   

 if (myfile.is_open()) { /* ok, proceed with output */ }



Fermeture d'un fichier
Lorsque nous aurons terminé avec notre opérations d'entrée et de sortie sur un fichier que nous allons fermer en sorte que ses ressources soient de nouveau disponibles. Pour ce faire, nous devons appeler la fonction à la clôture de membre du flux (). Cette fonction de membre ne prend aucun paramètre, et ce qu'il fait est de vider les tampons associés et fermez le fichier:



   

 myfile.close();



Une fois cette fonction membre est appelée, l'objet de flux peut être utilisé pour ouvrir un autre fichier, et le fichier est de nouveau disponible pour être ouverts par d'autres procédés.

Dans le cas où un objet est détruit tout associé à un fichier ouvert, le destructeur appelle automatiquement la fonction de fermeture de membre ().

Les fichiers texte
flux de fichiers de texte sont ceux où nous n'incluons pas l'ios :: drapeau binaire dans leur mode d'ouverture. Ces fichiers sont destinés à stocker du texte et donc toutes les valeurs que nous entrée ou la sortie de / vers eux peuvent souffrir certaines transformations de mise en forme, qui ne correspondent pas nécessairement à leur valeur binaire littéral.

Données opérations de sortie sur les fichiers texte sont effectuées de la même manière que nous opérions avec cout:

   

 // writing on a text file #include <iostream> #include <fstream> using namespace std; int main () { ofstream myfile ( "example.txt" ); if (myfile.is_open()) { myfile << "This is a line.\n" ; myfile << "This is another line.\n" ; myfile.close(); } else cout << "Unable to open file" ; return 0; }

   

  [Fichier example.txt]
  Il s'agit d'une ligne.
  C'est une autre ligne.



La saisie des données à partir d'un fichier peut également être effectuée de la même manière que nous l'avons fait avec cin:

   

 // reading a text file #include <iostream> #include <fstream> #include <string> using namespace std; int main () { string line; ifstream myfile ( "example.txt" ); if (myfile.is_open()) { while ( getline (myfile,line) ) { cout << line << endl; } myfile.close(); } else cout << "Unable to open file" ; return 0; }

   

  Il s'agit d'une ligne.
  C'est une autre ligne.



Ce dernier exemple lit un fichier texte et affiche son contenu sur l'écran. Nous avons créé une boucle while qui lit le fichier ligne par ligne, en utilisant getline . La valeur retournée par getline est une référence à l'objet de flux lui-même, qui, lorsqu'il est évalué comme une expression booléenne (comme dans cette boucle while) est vraie si le flux est prêt à davantage d'opérations, et faux si soit la fin du fichier a été atteint ou si une autre erreur s'est produite.

Vérification drapeaux d'état
En plus de la bonne (), qui vérifie si le flux est prêt pour les opérations d'entrée / sortie, d'autres fonctions membres existent pour vérifier les états spécifiques d'un flux (tous retournent une valeur bool):

mauvais ()
    Renvoie true si une lecture ou d'écriture échoue. Par exemple, dans le cas que nous essayons d'écrire dans un fichier qui n'est pas ouvert en écriture ou si l'appareil où nous essayons d'écrire n'a pas d'espace à gauche.
fail ()
    Retourne vrai dans les mêmes cas que le mauvais (), mais aussi dans le cas où une erreur de format qui se passe, comme quand un caractère alphabétique est extrait lorsque nous essayons de lire un nombre entier.
eof ()
    Renvoie true si un fichier ouvert en lecture a atteint la fin.
bon ()
    C'est le drapeau de l'Etat le plus générique: il retourne faux dans les mêmes cas où appeler une des fonctions précédentes reviendrait vrai.


Pour réinitialiser les drapeaux de l'Etat vérifiés par l'une de ces fonctions membres que nous venons de voir, nous pouvons utiliser la fonction de membre clear (), qui ne prend aucun paramètre.

obtenir et de mettre des pointeurs de flux
Toutes les E / o objets de ruisseaux ont, au moins, un pointeur de flux interne:

ifstream, comme istream, a un pointeur connu sous le pointeur de lecture qui pointe vers l'élément devant être lus à la prochaine opération d'entrée.

ofstream, comme ostream, a un pointeur connu sous le pointeur d'écriture qui pointe vers l'emplacement où le prochain élément doit être écrite.

Enfin, fstream, hérite à la fois, l'obtenir et les pointeurs de vente, de iostream (qui est lui-même issu des deux istream et ostream).

Ces pointeurs de flux internes qui pointent vers les lieux de lecture ou d'écriture dans un flux peuvent être manipulés à l'aide des fonctions membres suivants:

tellg () et tellp ()
Ces deux fonctions membres n'ont pas de paramètres et renvoient une valeur de type pos_type membre, qui est un type de données entier représentant la position actuelle du pointeur de flux get (dans le cas de tellg) ou le pointeur de flux mettre (dans le cas de tellp ).

seekg () et seekp ()
Ces fonctions permettent de modifier la position de l'obtenir et de mettre des pointeurs de flux. Ces deux fonctions sont surchargés avec deux prototypes différents. Le premier prototype est:

seekg (position);
seekp (position);

L'utilisation de ce prototype le pointeur de flux est changé à la position de la position absolue (en comptant à partir du début du fichier). Le type de ce paramètre est le même que celui retourné par les fonctions tellg et tellp: le type pos_type membre, qui est une valeur entière.

L'autre prototype de ces fonctions est le suivant:

seekg (offset, direction);
seekp (offset, direction);

L'utilisation de ce prototype, la position du pointeur obtenir ou mettre est réglé sur une valeur de décalage par rapport à un moment spécifique déterminé par la direction du paramètre. Décalage est du type off_type d'élément, qui est aussi un type entier. Et la direction est de type seekdir, qui est un type énuméré (enum) qui détermine le point à partir duquel décalage est compté à partir, et qui peut prendre les valeurs suivantes:

ios :: mendier     décalage compté à partir du début du flux
ios :: actu     décalage compté à partir de la position courante du pointeur de flux
ios :: fin     décalage compté à partir de la fin du flux

L'exemple suivant utilise les fonctions de membres, nous venons de le voir pour obtenir la taille d'un fichier:



   

 // obtaining file size #include <iostream> #include <fstream> using namespace std; int main () { long begin,end; ifstream myfile ( "example.txt" ); begin = myfile.tellg(); myfile.seekg (0, ios::end); end = myfile.tellg(); myfile.close(); cout << "size is: " << (end-begin) << " bytes.\n" ; return 0; }

   

  taille est: 40 octets.



Les fichiers binaires
Dans les fichiers binaires, les données d'entrée et de sortie avec les opérateurs d'extraction et d'insertion (<< et >>) et fonctionne comme getline n'est pas efficace, car nous n'avons pas besoin de formater les données, et les données ne peuvent pas utiliser les codes de séparation utilisés par des fichiers texte à des éléments séparés (comme l'espace, saut de ligne, etc ..).

Les flux de fichiers comprennent deux fonctions membres spécialement conçues pour les données binaires d'entrée et de sortie de façon séquentielle: écrire et lire. Le premier (écriture) est une fonction membre de ostream hérité par ofstream. Et en lecture est une fonction membre de istream qui est héritée par ifstreamet. Objets de fstream de classe ont tous deux membres. Leurs prototypes sont:

write (memory_block, taille);
lire (memory_block, taille);

Où memory_block est de type "pointeur vers un char" (char *), et représente l'adresse d'un tableau d'octets, où les données lues sont stockées ou à partir duquel les éléments de données qui doivent être écrites sont prises. Le paramètre de taille est une valeur entière qui indique le nombre de caractères à lire ou à écrire à partir de / vers le bloc de mémoire.


   

 // reading a complete binary file #include <iostream> #include <fstream> using namespace std; ifstream::pos_type size; char * memblock; int main () { ifstream file ( "example.bin" , ios::in|ios::binary|ios::ate); if (file.is_open()) { size = file.tellg(); memblock = new char [size]; file.seekg (0, ios::beg); file.read (memblock, size); file.close(); cout << "the complete file content is in memory" ; delete [] memblock; } else cout << "Unable to open file" ; return 0; }

   

  le contenu complet du fichier en mémoire



Dans cet exemple, le fichier entier est lu et mémorisé dans un bloc de mémoire. Examinons comment cela se passe:

Tout d'abord, le fichier est ouvert avec l'ios :: drapeau mangé, ce qui signifie que le pointeur get sera positionné à la fin du fichier. De cette façon, lorsque nous appelons à tellg membre (), nous allons directement obtenir la taille du fichier. Notez le type que nous avons utilisé pour déclarer taille variable:



   

 ifstream::pos_type size;



ifstreamet :: pos_type est un type particulier de mémoire tampon et le positionnement de fichier et le type retourné par file.tellg (). Ce type est défini comme un type entier, donc nous pouvons effectuer sur elle les mêmes opérations que nous menons sur toute autre valeur entière, et peut sans risque être converti en un autre type entier assez grand pour contenir la taille du fichier. Pour un fichier avec une taille inférieure à 2 Go que nous pourrions utiliser int:


   

 int size; size = ( int ) file.tellg();



Une fois que nous avons obtenu la taille du fichier, nous demandons l'attribution d'un bloc de mémoire suffisamment grande pour contenir l'intégralité du fichier:



   

 memblock = new char [size];



Juste après cela, nous procédons à régler le pointeur de lecture au début du fichier (n'oubliez pas que nous avons ouvert le fichier avec ce pointeur à la fin), puis lire le fichier entier, et enfin fermer:



   

 file.seekg (0, ios::beg); file.read (memblock, size); file.close();



A ce stade, nous pourrions travailler avec les données obtenues à partir du fichier. Notre programme annonce simplement que le contenu du fichier en mémoire, puis se termine.

Tampons et synchronisation

Lorsque nous travaillons avec les flux de fichiers, ceux-ci sont associés à une mémoire tampon interne de type streambuf. Ce tampon est un bloc de mémoire qui joue le rôle d'intermédiaire entre le flux et le fichier physique. Par exemple, avec un ofstream, chaque fois que la fonction put membre (qui écrit un seul caractère) est appelée, le personnage n'est pas écrit directement dans le fichier physique avec qui le courant est associé. Au lieu de cela, le caractère est inséré dans un tampon intermédiaire de flux.

Lorsque le tampon est vidé, toutes les données qu'il contient sont écrites sur le support physique (s'il s'agit d'un flux de sortie) ou simplement libérés (s'il s'agit d'un flux d'entrée). Ce processus est appelé synchronisation et se déroule dans l'une des circonstances suivantes:

    Lorsque le fichier est fermé: avant de fermer un fichier tous les tampons qui n'ont pas encore été vidées sont synchronisés et toutes les données en attente sont écrites ou lues sur le support physique.
    Lorsque la mémoire tampon est pleine: Tampons ont une certaine taille. Lorsque la mémoire tampon est pleine, elle est automatiquement synchronisé.
    Explicitement, avec des manipulateurs: Lorsque certains manipulateurs sont utilisés sur les cours d'eau, une synchronisation explicite a lieu. Ces manipulateurs sont: flush et endl.
    Explicitement, avec un membre de la fonction sync (): Appel fonction de synchronisation de membre de flux (), qui ne prend aucun paramètre, provoque une synchronisation immédiate. Cette fonction retourne une valeur int égal à -1 si le flux n'a pas de tampon associé ou en cas d'échec. Dans le cas contraire (si le tampon de flux a été synchronisé avec succès), elle retourne 0. 
Publié par Drupal Study