2010-02-21 5 views
2

Considérons le programme C++ suivant, qui prend un fichier et imprime chaque ligne. C'est une tranche d'un programme plus important où je joins plus tard au dossier, basé sur ce que je vois.Pourquoi ne puis-je pas lire et ajouter avec std :: fstream sur Mac OS X?

#include <fstream> 
using std::fstream; 
#include <iostream> 
#include <string> 
using std::string; 

int main() 
{ 
fstream file("file.txt", fstream::in | fstream::out | fstream::app); 

string line; 
while (std::getline(file, line)) 
    std::cerr << line << std::endl; 

return 0; 
} 

Maintenant, appliquez cette version de file.txt (Un mot sur la première ligne, suivi d'un saut de ligne):

Rain 

Sur ma machine (Snow Leopard), ce imprime rien. En y regardant de plus près, le premier appel à getline échoue. Étrangement, il échoue également si j'ajoute une deuxième ligne: toujours rien n'est imprimé!

Quelqu'un peut-il résoudre ce mystère?

+0

Votre programme fonctionne pour moi, donc cela peut être un bug dans votre environnement. Avez-vous essayé d'ouvrir en lecture seule, c'est-à-dire juste 'fstream :: in'? –

+0

Fonctionne bien ici aussi, faites comme Earwicker dit et vérifiez que votre fichier est effectivement ouvert. – Manuel

+0

BTW, vous envoyez le texte à 'std :: cerr' -' std :: cout' serait plus normal pour la sortie réelle. 'std :: cerr' est pour le rapport d'erreur (comme dans ma réponse). –

Répondre

9

Quand vous dites:

fstream file("file.txt", fstream::in | fstream::out | fstream::app); 

vous ouvrez le fichier en mode append - à savoir à la fin. Il suffit de l'ouvrir en mode lecture:

fstream file("file.txt", fstream::in); 

ou utiliser un ifstream:

ifstream file("file.txt"); 

Et bien sûr, comme le suggère Earwicker, vous devriez toujours tester que l'ouverture a réussi.

Si vous êtes déterminé à ouvrir en mode append, vous pouvez déplacer le pointeur de lecture explicitement:

#include <fstream> 
#include <iostream> 
#include <string> 
using namespace std; 

int main() { 
    fstream file("afile.txt", ios::in | ios::out | ios::app); 
    if (! file.is_open() ) { 
     cerr << "open failed" << endl; 
     return 1; 
    } 
    else { 
     file.seekg(0, ios::beg); // move read pointer 
     string line; 
     while(getline(file, line)) { 
      cout << line << endl; 
     } 
    } 
} 

Edit: Il semble que la combinaison des drapeaux utilisés dans l'ouverture du dossier conduit à la mise en œuvre comportement spécifique. Le code ci-dessus fonctionne avec g ++ sur Windows, mais pas avec g ++ sur Linux.

+0

Mais la position de lecture n'est-elle pas indépendante de la position d'écriture? –

+0

Apparemment non - c'est la bonne réponse. Les gens qui ont dit qu'ils l'ont essayé sur leurs propres systèmes peuvent avoir été fibbing! :) –

+0

@Earwicker - c'est une accusation forte, et malheureusement pour vous un totalement injustifié. Et de penser que j'ai upvoted votre réponse ... – Manuel

2

Vous devriez vérifier si le fichier a été effectivement ouvert:

if (!file) 
    std::cerr << "Oh dear" << std::endl; 

Mise à jour: en fait le fichier a probablement été ouvert, mais il est en mode append - voir la réponse de Neii.

Mise à jour 2: okay, faux encore. Dans le g ++ de Leopard au moins, le fichier ne sera pas ouvert parce que le drapeau app est incompatible avec le drapeau in. Ainsi, la vérification ci-dessus affichera Oh dear.

En MSVC++, il avance et ouvre le fichier, apparemment avec la position de lecture au début, ce qui explique pourquoi d'autres personnes l'ont vu fonctionner et je m'excuse d'avoir douté de leur véracité!