fstream / Modifier une valeur spécifique dans un fichier C++

fstream / Modifier une valeur spécifique dans un fichier C++ - C++ - Programmation

Marsh Posté le 18-09-2012 à 18:29:02    

Bonjour,
 
Une questino sur un problème sans doute très simple, mais sur lequel je n'ai pas trouvé d'aide précise et claire.
Je voudrais ecrire un fichier avant d'en changer plus tard certaines valeurs spécifiques répondant à des critères donnés.
 
Plus simplement, dans une version basique de ce problème, j'ai le code :
 

Code :
  1. #include <iostream>
  2. #include <fstream>
  3. #include <string>
  4. using namespace std;
  5. int main()
  6. {
  7. int i,j,k,n;
  8. n = 10;
  9. string filename;
  10. filename = "file.txt";
  11. cout << filename << endl;
  12. // Write
  13. ofstream ofs;
  14. ofs.open(filename.c_str());
  15. for(i=-n;i<n;i++)
  16. {
  17.  for(j=-n;j<n;j++)
  18.   ofs << i*j << " ";
  19.  ofs << endl;
  20. }
  21. ofs.close();
  22. // Read and change
  23. fstream fs;
  24. fs.open(filename.c_str(), ios::in | ios::out );
  25. for(i=-n;i<n;i++)
  26. {
  27.  for(j=-n;j<n;j++)
  28.  {
  29.   fs >> k;
  30.   if (k<0)
  31.   {
  32.    fs << -k;
  33.   }
  34.  }
  35. }
  36. }


 
J'écris ainsi un fichier simple au début (avec des valeurs positives ou négatives), avant d'en relire le contenu.
Je voudrais ainsi, à titre d'exemple, en changer les valeurs positives en négatives, mais il semble que cela ne soit fonctionne pas.
 
Le fichier demeure inchangé, bien que le test soit vérifié régulièrement. Qu'est ce que j'ai raté ? Est-ce que je dosi changer quelquechose dans ces dernières lignes ?
Je pensais que l'utilisation d'un ' fstream ' résoudrais le problème mais ce n'est apparemment pas le cas.
 
D'avance merci de votre aide,
 
Nathan

Reply

Marsh Posté le 18-09-2012 à 18:29:02   

Reply

Marsh Posté le 18-09-2012 à 23:38:04    

Bonjour !
 
Tout d'abord, votre programme ne teste pas que les actions ont été correctement effectuées !
 
 -> la méthode "open" ne renvoie rien, il faut tester que l'ouverture s'est bien passée avec la méthode "isopen"
 
 -> Après chaque opération ">>" et "<<" il peut être intéressant de tester le retour à l'aide de la méthode "fail" (qui renvoie "true" si une erreur s'est produite durant la lecture/écriture).
 
En instrumentant votre programme, vous vous rendrez compte, durant la deuxième phase, que les lectures se passent correctement puis que la première écriture se passe mal. Ensuite, toutes les opérations échouent (les pointeurs de lecture / écriture sont positionnés à -1, plus aucune opération n'est réellement effectuée).
 
Pourquoi ce fonctionnement ?
 
Je ne saurais vous le dire exactement ... Mais, de toutes façons, modifier des valeurs dans un fichier "texte", avec donc des valeurs qui n'ont pas la même taille, ne peut fonctionner correctement (remplacer dans le texte "-10" par "10" donnerait "100" à la relecture).
 
Par ailleurs, quand vous lisez (<< ) dans le fichier, le pointeur de lecture et d'écriture sont décalés (ce qui signifie que vous écririez dans le fichier juste après ce que vous venez de lire, au lieu de remplacer ...).
 
Si vous voulez faire ce genre de modifications :
 
 * Lisez et écrivez des valeurs en binaire, qui ont tous la même taille,
 * Avant de réécrire, décalez le pointeur d'écriture pour réécrire à l'endroit de votre lecture, pas à la suite ...
 
Sinon, une version qui fonctionne presque (les fonctionnement n'est pas exactement le même en début de ligne, en milieu de ligne et en fin de ligne) serait la suivante  (mais la façon de faire est "très moche" :) ):  
 

Code :
  1. #include <iostream>
  2.     #include <fstream>
  3.     #include <string>
  4.     using namespace std;
  5.     int main()
  6.     {
  7.     int i,j,k,n;
  8.     n = 10;
  9.     string filename;
  10.     filename = "file.txt";
  11.     cout << filename << endl;
  12.     // Write
  13.     ofstream ofs;
  14.     ofs.open(filename.c_str());
  15.     for(i=-n;i<n;i++)
  16.     {
  17.      for(j=-n;j<n;j++)
  18.       ofs << i*j << " ";
  19.      ofs << endl;
  20.     }
  21.     ofs.close();
  22.     // Read and change
  23.     fstream fs;
  24.     fs.open(filename.c_str(), ios::in | ios::out );
  25.     long pos = 0;
  26.     for(i=-n;i<n;i++)
  27.     {
  28.      for(j=-n;j<n;j++)
  29.      {
  30.       fs >> k;
  31.       if (k<0)
  32.       {
  33.        fs.seekg(pos+1);
  34.        fs << -k << " " ; // <-- On rajoute un espace pour que le nombre positif prenne autant de place que le nombre négatif pour ne pas tout décaler ...
  35.       }
  36.       pos = fs.tellg();
  37.      }
  38.     }
  39.     }


 
J'espère avoir été clair et vous avoir aidé !
 
Bon courage !


Message édité par Farian le 18-09-2012 à 23:41:40
Reply

Marsh Posté le 19-09-2012 à 14:10:46    

Bonjour,

 

Merci de votre aide.
Je me suis tourne finalement vers un fichier Binaire pour gérer plus simplement ces opérations. La lecture et l'écriture sont correcte mais je ne parviens pas à modifier comme je le souhaite un élément. J'ai l'écriture :

 
Code :
  1. fstream fs;
  2. fs.open(filename.c_str(), ios::in | ios::out | ios::binary );
  3. unsigned long pos;
  4. for(i=-n;i<n;i++)
  5. {
  6.  for(j=-n;j<n;j++)
  7.  {
  8.   pos = fs.tellp();
  9.   fs.read(reinterpret_cast<char*> (&k), sizeof(int));
  10.   if (k<0)
  11.   {
  12.    cout << "Change val = " << k << " in " << -k << " / " << i << " " << j << endl;
  13.    fs.seekg(pos);
  14.    k = -k;
  15.    fs.write(reinterpret_cast<char*> (&k), sizeof(int));
  16.   }
  17.  }
  18. }
 

Mais elle ne semble pas correcte car seule la première valeur est modifiée et pas les suivantes que je trouve.

 

Quel pourrait être le problème ?
Ai je fait une erreur dans le choix des opérateurs binaires ?

 

D'avance merci de votre réponse,

 

G_Nathan


Message édité par G_Nathan le 19-09-2012 à 14:12:09
Reply

Marsh Posté le 19-09-2012 à 17:17:17    

Bonjour,

 

En pratique, j'avais oublié de mettre une commande '  fs.flush (); ' pour forcer l'écriture immédaite de la valeur. L'écriture corrigée :

 
Code :
  1. // Change
  2. fstream fs;
  3. fs.open(filename.c_str(), ios::in | ios::out | ios::binary );
  4. ifstream::pos_type pos;
  5. for(i=-n;i<n;i++)
  6. {
  7.  for(j=-n;j<n;j++)
  8.  {
  9.   pos = fs.tellg();
  10.   fs.read(reinterpret_cast<char*> (&k), sizeof(int));
  11.   if (k<0)
  12.   {
  13.    cout << "Change val = " << k << " in " << -k << " / " << i << " " << j << endl;
  14.    fs.seekp(pos);
  15.    k = -k;
  16.    fs.write(reinterpret_cast<char*> (&k), sizeof(int));
  17.    fs.flush ();
  18.   }
  19.  }
  20. }
 

semble fonctionner.

 

Y a -t-il quelque chose de choquant dans cette écriture ou voyez vous une manière plus simple de procéder en binaire ?

 

D'avance merci de vos conseils,

 

G_Nathan


Message édité par G_Nathan le 19-09-2012 à 17:17:28
Reply

Marsh Posté le 19-09-2012 à 19:32:38    

Ce me semble bon.
Éventuellement, tu peux rajouter un const au cast du write: fs.write(reinterpret_cast<const char*> (&k), sizeof(int));
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 20-09-2012 à 19:18:08    

Ne vaut il pas mieux écrire un fichier en // de celui qu'on lit ?


---------------
Ta peau de nacre noir, la courbe de ton cul
Reply

Marsh Posté le 21-09-2012 à 00:29:23    

Pourquoi? pour aller plus vite?
Ça dépend de ses données. S'il a beaucoup d'inversions, oui. S'il en a peu, non.
A+,

Message cité 1 fois
Message édité par gilou le 21-09-2012 à 00:30:23

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 21-09-2012 à 09:13:01    

gilou a écrit :

Pourquoi? pour aller plus vite?
Ça dépend de ses données. S'il a beaucoup d'inversions, oui. S'il en a peu, non.
A+,


 
Je ne sais pas, en fait je n'ai jamais rencontré ce cas (lire et écrire dans un fichier avec le même stream), et ça ne me serait pas venu à l'idée, du coup je me demandais s'il y avait une raison :D


---------------
Ta peau de nacre noir, la courbe de ton cul
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed