2010-06-25 14 views
0

Dans mon programme, j'ai redirigé stdout pour imprimer dans un fichier 'console.txt'. Une fonction écrit à ce fichier comme ceci:Données de vidange étranges lors de l'ouverture d'un fichier précédemment tronqué

void printToConsole(const std::string& text, const TCODColor& fc, const TCODColor& bc) 
    { 
     // write the string 
     cout << text << "@"; 

     // write the two color values 
     cout << static_cast<int>(fc.r) << " " 
      << static_cast<int>(fc.g) << " " 
      << static_cast<int>(fc.b) << " " 
      << static_cast<int>(bc.r) << " " 
      << static_cast<int>(bc.g) << " " 
      << static_cast<int>(bc.b) << " " << endl; 
    } 

J'ai une fonction qui lit ce fichier qui ressemble à ceci:

void Console::readLogFile() 
    { 
     ifstream log("console.txt", ifstream::in); 
     if(!log.is_open()) 
     { 
      cerr << "ERROR: console.txt not found!" << endl; 
      return; 
     } 

     // read new input into Console 
     string str; 
     while(getline(log, str)) 
     { 
      cerr << "str: " << str << endl; 
      /* do stuff with str here */ 
     } 
     cerr << endl; 

     log.close(); 
     clearLogFile(); 
    } 


    void Console::clearLogFile() 
    { 
     ofstream("console.txt", ios_base::trunc); 
    } 

La première fois par la readLogFile, tout fonctionne bien. Après, cependant, il commence à avoir des problèmes. Il lira dans la première ligne de console.txt comme une chaîne vide. J'ai parcouru le programme avec console.txt ouvert dans gvim, et surveillé comment cela a changé. La première fois, quand il a fonctionné correctement, console.txt ressemble à quelque chose comme ceci:

1 moved [email protected] 191 191 0 0 0 
    2 Player [email protected] 191 191 0 0 0 
~ 
~ 

qui est comme il devrait être. Le programme passe ensuite à clearLogFile, après quoi console.txt est vide. Cependant, la deuxième fois à travers, quand j'ouvre le ifstream, console.txt ressemble à ceci:

1 ^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@ 
    ^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@moved [email protected] 191 191 0 0 0 
    2 Player [email protected] 191 191 0 0 0 
~ 
~ 

Cette fois-ci, quand getline lit la première ligne dans str, str est vide. Bizarrement, la ligne cerr << "str: " << str << endl; affiche toujours str comme "déplacé vers le haut. @ 191 191 191 0 0 0", même si l'inspection de str dans gdb révèle qu'il est vide.

Quelqu'un sait ce qui se passe ici?

Répondre

0

La routine en cours d'écriture ne réinitialise pas sa position avant de réécrire le fichier. Par conséquent, il commence à un décalage dans le fichier cible.

Je crois qu'un cout.seekp (0) après l'exécution de l'écriture réinitialisera le pointeur d'écriture, redémarrant ainsi l'écriture au début du fichier.

Vous allez probablement avoir beaucoup de problèmes avec la cohérence du contenu du fichier journal avec la façon dont vous l'utilisez.

Commentaire ajouté ici, comme je ne peux pas le formatage dans la boîte de commentaire ...

En redéfinissant le pointeur de fichier après chaque écriture, il n'y aura jamais une seule ligne dans le fichier de sortie. Vous devez vous assurer que vous l'avez lu avant d'y écrire, sinon les nouvelles données seront écrasées par les anciennes données, ou pire, elles seront partiellement remplacées.

par exemple. écriture 1:

Player moved 1 2 3 4 

par exemple. écrire 2:

Player fell over 

laisserais:

Player fell over 
3 4 

Dans le fichier écrit si le lecteur n'a pas y arriver avant que l'écrivain a fait son deuxième écriture. Il peut être préférable d'utiliser un fichier explicite, plutôt que d'utiliser cout, ou vous pouvez vous souvenir de la position de lecture entre les lectures et chercher à cela avant d'effectuer votre prochaine lecture, mais cela vous laisse avec un fichier journal en constante augmentation.

HTH

+0

Cela a résolu le problème, merci. Quel genre de problèmes pensez-vous que je vais avoir? Des suggestions sur comment je pourrais l'utiliser mieux? – Max

+0

En réinitialisant le pointeur de fichier après chaque écriture, il n'y aura plus qu'une seule ligne dans le fichier de sortie. Vous devez vous assurer que vous l'avez lu avant d'y écrire, sinon les nouvelles données seront écrasées par les anciennes données, ou pire, elles seront partiellement remplacées. par exemple. première écriture: joueur déplacé 1 2 3 4 5 Deuxième écriture: joueur est tombé sur laisse ce qui suit dans le fichier: joueur est tombé sur si le lecteur n'a pas obtenu la fichier avant que l'écrivain a écrit le deuxième message. C'est l'un des problèmes fondamentaux de la synchronisation. – Petesh

+0

Je mets 'cout.seekp (0)' après 'ofstream (" console.txt ", ios_base :: trunc);' dans 'clearLogFile', donc il ne réinitialisera le pointeur qu'après avoir effacé tout de console.txt, pas après chaque écriture. Cela semble fonctionner correctement jusqu'à présent. Voyez-vous d'autres problèmes? – Max