Je poste ici, car j'ai actuellement un problème avec fstream , et que je n'arrive pas à résoudre.
Pour résumer le tout, j'ouvre un flux, de cette façon: "m_file.open(f_dir,ios::in|ios::out);", puis je cherche à en afficher le contenu, via get().
Cependant, le problème est que à chaque get(), le curseur passe d'octet en octet (parfois moins, parfois plus) plutôt que de lire caractère après caractère (byte par byte). J'ai établit ce diagnostique grâce à tellg(), mais je n'ai aucune idée de la raison du problème, ni pourquoi cette valeur ne s'incrémente pas toujours de 8 .
Le seul moyen que j'ai trouvé pour empêcher ce dépassement étrange, est d'ajouter à l'ouverture du fichir le paramètre "ios::binary"; mais je ne vois as en quoi ça changerai quelque chose (de plus ça désactive l'utilisation de '\n' ou 'endl' lors de l'écriture dans le fichier ).
Voici les deux méthodes que j'emploie sur mon fichier pour l'ouvrir et le lire:
void Ini_File::OpenFile(constchar* f_dir) {
m_file.open(f_dir,ios::in|ios::out);//J'ouvre mon fichier
m_dir=f_dir;//J'enregistre le répertoire du fichier.
if(m_file)
cout<<f_dir<<" ouvert avec succes!\n"; else
cout<<f_dir<<" introuvable. Veuillez verifier que ce fichier existe et/ou qu'il n'est pas dejà en cours d'utilisation.\n"; }
m_file.seekg(0, ios::beg);//Je reviens au début du fichier
while(!this->end())//J'ai fais une alternative au .eof(), qui compare la position actuelle à la taille du fichier, ce qui evite un dépassement de mémoire, ou une perte du flux. {
m_file.get(cache);//Je récupère le caractère actuel
content+=cache;//Je l'ajoute au string complet }
m_file.seekg(0, ios::beg);//Je revient ensuite au début pour l'opération suivante return content;//Et finalement je renvoie le contenu du fichier. }
bool Ini_File::end() { if(m_file.tellg()<m_size)//Je vérifie que le curseur n'a pas dépassé la taille du fichier (=m_size) returnfalse; else returntrue; }
J'utilise ici, un simple "get()", mais même avec un "getline", fstream me zappe les caractères ...
Voila! Donc si l'un de vous a déjà eût ce problème, pourrait-il me dire comment il a fait pour le résoudre, ou si vous voyez une erreur dans mon code, pourriez-vous me dire où?
Lol j'en étais sur que tu allais me sortir ça ...
Non plus sérieusement , j'avais bien lu ta doc (enfin je penses ?): et si je ne me trompes pas , mon problème vient avec l'ouverture du fichier à la base ? Où je n'ai pas mis "ios::app" ni "ios::trunc".
Si c'est bien là mon erreur, alors il y a ausi un problème ailleur, car en choisissant cette option (pour moi "ios:app", je perds instantanément le flux (tellg() me renvoie -1).
Et si c'est vraiment pas ça , je ne vois pas trop ce que ça peux être (un petit indice? ) ...
Non, je n'essaye pas d'écrire en plein milieu du fichier (dumoin pas au moment où survient le bug ).
En fait, à chaque appel de "get()", le curseur devrait normalement se déplacer d'un byte en avant (de caractère à caractère), hors là il se déplace de 8 en 8.
Exemple si j'ai un fichier texte contenant: "Althar93"
Au premier appel de "get()", il me renverra "A" (normal jusque là ), mais au suivant: directement "3", au lieu de chaque caractère comme il devrait.
Pour le coup du append, j'étais au courant, mais le problème et que je perds instantanément le flux: en gros pas moyen de me placer au début, ni d'écrire quoique ce soit à la fin...
Comme j'ai dis, si je fais appel à tellg() juste après l'ouverture du fichier en mode ios::app, il me renvoie directemet -1 (signe qu'il y a une erreur... ), et m'indique aussi (avec le test d'ouverture) que le fichier est "introuvable. Veuillez..."
Pourtant ce fichier est bien là où il faut, puisque en avec le mode d'ouverture "ios::binary", il arrive à ouvrir le fichier, en extraire le contenu, écrire dedans, etc. La seule chose que je ne peux alors plus faire est de mettre des sauts de lignes (il me met des cubes à la place).
si tu lis octets par octets, utilise ios::binary.
Si tu ne le fais pas, il va réagir pour "universaliser" le \n
En gros, il va sauter des caracteres, parce que
- sous Windows, un \n c'est 2 octets : 0x0D 0x0A
- sous Linux, c'est uniquement 0x0D
- sous Max, c'est 0x0A 0x0D
Il est possible qu'il y aie encore des spécifications.
L'ouverture en mode texte parre ces différences entre codages, mais si tu lis en binaire, tu es mort :
car si tu lis un 0x0D, il liras aussi l'octet suivant sous Windows.
un conseil, travaille en ios::binary : ça fait vraiment du bas niveau (octet par octet), sauf si tu veux lire un fichier texte pur.
Merci beaucoups pour l'info, j'y vois un peu plus clair à présent .
Cependant, je ne sais pas dans ce cas, quelle méthode d'ouverture choisir : binaire ou texte?
De plus, ça n'explique pas pourquoi rien qu'en lecture (alors que sur le tuto de Xav57 ça fonctionne) et ce même avec un fichier texte pur (pas en mode binaire), qu'il me zappe des caractères.
Le plus étrange est que comme j'ai dis plus haut, le saut de caractère n'est pas de valeur contstante ; du coup certains passages sont à presque complets, alors que d'autres sont juste des lettres collées les unes derrières les autres.
Je me suis dis que mon fichier pouvait être corrompu , mais le même problème survient sur 3 fichiers différents (mon fichier comme ci-dessous, un texte pur, et un autre fichier test).
Les fichiers que ma classe est censée lire sont des la forme:
Du coup, je pourrais theoriquement oublier la notion de sauts de ligne, étant donné que je lis caractère par caractère (mode binaire), mais je perds une autre propriété, la lisibilité (que le fichier soit aussi facilement lisible par nous même et que l'on puisse facilement le modifier à la main).
De même (et ça semble contre-dire ce que tu me dis là), je suis étonné qu'à l'affichage de mon texte (via un get() et en mode binaire, j'obtienne correctement les sauts de lignes).
A votre avis quelle est la meilleure méthode à employer (si visiblement mon problème n'est pas résolvable)? Mettre en place deux flux (binaire pour la lecture, et texte pour l'écriture?)? Dire adieu à la possibilité de modifier le fichier à la main(suppréssion des sauts de ligne)?
Mais la première méthode me parait bien lourde et la seconde me plait pas des masses ...
Je n'avais pas autant de problème en utilisant FILE*, mais apparemment ce n'est pas du C++...
Disons que si c'est pour relire le fichier : meme si c'est un fichier texte, tu peux le relire en binaire.
Tu lis caractere par caractere en binaire, et quand tu croises un 0x0D ou un 0x0A, tu vois que tu reviens a la ligne : aucun probleme de lisibilité si j'ose dire
Et ça ne t'empechera pas de le modifier avec un bloc note ! en ios::binary, tu controles tout, tu detectes les sauts de ligne qui sont codés pas 0x0D et/ou 0x0A.
FILE* a le meme genre de soucis avec "r" ou "rb" pour l'acces en lecture
Ma classe a pour objet de modifier elle même les valeurs contenue dans le fichier (la modif à la main c'est en plus ).
En gros, elle ouvre le fichier, et l'utilisateur via des méthodes, peux aller aux différents groupes, puis item, et peut au choix en extraire a valeur, ou la remplacer par une nouvelle.
Du coup, même si le fichier est lisible par la classe et modifiable par l'utilisateur, elle ne l'est pas par la classe, et donc elle perd tout son intêret/utilité.
Je viens de faire quelques tests, en scindant mon fstream en deux flux, et j'ai toujours le même problème de sauts de caractères. Avec getline(), j'arrive à obtenir la plupart du contenu, mais il reste des sauts étranges de caractères (il manque la moitié gauche, si ce n'est du "n'importe quoi") ...
ios::app me fais toujours instantanément perdre le flux, et trunc ne me sert à rien...
Par contre, j'ai constaté que le texte est lu correctement, tant qu'il n'y a pas à pasde sauts de ligne (même avec un texte pur). En gros le texte s'affiche correctement tant qu'il n'y a pas de sauts de ligne après lui.
Voila un exemple pour illustrer (exactement la même disposition):
Mon code ne fonctionne pas
Resultat:
Mon code ne fonctionne pas
Mais avec la disposition changée, étendu sur deux lignes:
Mon code ne fonctionne
pas
Resultat:
Mncd efnton
pas
Mais avec la disposition changée, étendu sur trois lignes:
Mon code ne
fonctionne
pas
Resultat:
M dn
ocine
pas
Comme vous pouvez le voir, plus il y a de lignes, et le plus le contenu devient n'importe quoi...
Et j'ai même l'impression qu'à chaque fois il saute n_lignes caractères (comptez bien, vous verrez )
Je commence à perdre patience . Je n'ai jamais eu de choses dans ce genre, d'habitude le problème était logique, hors là, c'est complètement aléatoire ...
J'avais oublié de le préciser avant : mais non plus ... Que ça soit avec fstream, ou ifstream, c'est exactement la même chose .
Je continue mes recherches sur le net, mais je n'arrive pas à trouver quoique ce soit qui s'approche de mon problème .
Edit: J'ai trouvé quelques liens sur le net, j'ai pu confirmer la raison de mon problème (cependant, je n'ai aucune idée de comment le résoudre).
Apparemment, la fonction "tellg()" est fautive, lorsque l'on est pas en mode "ios::binary", du coup elle a des résultats imprévisibles, tels que le saut de caractères, ou un renvoie d'erreur (ce qui bloque le flux) sans raison, etc...
A la base mon texte ne s'affichait pas en mode texte pur à cause de cela, car une fois ma fonction "end()" modifiée et remplacée par ça:
Le contenu s'affiche correctement, sans aucun problème . Cependant, ce n'est pas le seul endroit où je me sers de tellg(), ni surtout le seul endroit où j'ai besoin de connaître la position exacte du curseur.
De plus ma fonction modifiée, elle n'est plus du tout stable (puisqu'elle dépasse la mémoire du fichier, afin de renvoyer que l'on est à la fin).
Bref, je sais maintenant exactement où se situe le problème (sans avoir besoin de retourner tout mon code ), cependant de là à le résoudre ...
Chez vous, "tellg()" ne pose aucun problème? Je penses à Xav57 qui le cite dans son tuto, tu n'as aucun problème de ton côté avec cette fonction?
De plus, connaîtriez vous une alternative à ce "tellg()", quelque chose qui puisse servir à me renseigner sur la position active par rapport au fichier?
Je penses qu'une fois la taille du fichier identifié, je pourrais utiliser un compteur indépendant, qui s'incrémenterai avec chaque "get()", de façon à ne plus faire intervenir tellg(). Pensez-vous qu'il y ait une meilleure solution (partant déjà du principe que la mienne fonctionne )
En effet, c'était un peu du n'importe quoi... Enfing bon, j'ai enfin réussi à régler mon problème !
J'ai dis ADIEU à fstream (apporte plus de problème qu'autre chose ), et à la place j'ai maintenant deux flux, d'entrée (en binaire) et de sortie (en normal). De cette façon plus aucuns souçis avec tellg() , ou seekg() (oui oui, cette fonction aussi avait des blemes avec fstream, ou dumoins le mode texte pur) , et de plus, ça me fait une sécurité sur le flux et évite de faire n'importe quoi avec.
Voila, donc à présent toute ma classe fonctionne exactement comme je le voulais, allant de la lecture, à l'écriture (avec le remplaçement des données, sans que la disposition soit chamboulée lorsque je change la valeur d'un élément), de façon à ce que l'on puisse aussi facilement rajouter un élément/groupe à la main.
Bref un grand merci pour votre aide !! Vais pouvoir aller optimiser tout ça et virer tout mes "cout" de débuggage ...
D'expérience, on n'ouvre pas des flux textes en I+O. Soit on lit, soit on écrit. Si on veut remplacer, on passe par un fichier intermédiaire.
C'est ce que je te disais dans l'autre fil: on ne peut pas faire des remplacements autrement que caractère par caractère. Pas de suppression, pas d'insertion. Il existe des feintes pour éviter de manipuler trop de choses.
std::cout << "Remplaçons ``" << text << "'' par une ligne d'au plus " << text.length() << " caractères\n";
std::cout << "Veuillez saisir son nouveau contenu:\b-> ";
std::string newText;
std::cin >> newText;
newText.resize(text.length(), ' ');
std::cout << "Le nouveau texte sera: ``" << newText << "''" << std::endl;
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Recueil de code C et C++ http://fvirtman.free.fr/recueil/index.html
Recueil de code C et C++ http://fvirtman.free.fr/recueil/index.html