Partage
  • Partager sur Facebook
  • Partager sur Twitter

Ecriture au milieu d'un fichier .txt

Ecrire à l'endroit ou l'on a déplacer le curseur

Sujet résolu
    8 juin 2023 à 9:52:55

    Bonjour

    Je dispose d'un fichier .txt dans lequel j'ai écris, à la base, la phrase suivante :

    Bonjour, je suis une phrase ecrite dans un fichier.

    J'aimerai déplacer le curseur entre "Bonjour" et la virgule pour y écrire " tout le monde". En testant le code suivant, comme prévu, la console indique que le curseur se retrouve après le 7 ème caractère :

    #include <iostream>
    #include <fstream>
    #include <string>
    
    using namespace std;
    
    int main()
    {
        string const nomFichier("C:/Users/User/Documents/programme code blocks/programme en C++/modification_et_lecture_de_fichiers/scores.txt");
        /*Déclaration d'un flux permettant d'écrire
        dans le fichier sans écrasement*/
        ofstream monFlux(nomFichier.c_str(),ios::app);
    
        int position = monFlux.tellp(); //On récupère la position
        cout << "Nous nous situons au " << position << "eme caractere du fichier." << endl;
    
        monFlux.seekp(7, ios::beg);
        position = monFlux.tellp(); //On récupère la position
        cout << "Nous nous situons maintenant a son " << position << "eme caractere." << endl;
        monFlux << " tout le monde";
    
        return 0;
    }

    Le problème est qu'au lieu d'écrire le bout de phrase entre "Bonjour" et le virgule dans la phrase, le code va au bout de la phrase, et reviens à la ligne avant de l'écrire. Voici le fichier txt après avoir compilé deux fois :

    Il semblerait donc qu'il manque une instruction pour empêcher ce comportement et compléter ce code. Quelqu'un connaîtrait-il une instruction qui permet cela ?

    Cordialement

    -
    Edité par 1Stark 8 juin 2023 à 9:54:11

    • Partager sur Facebook
    • Partager sur Twitter
      8 juin 2023 à 13:32:11

      Hm j'ai pas + d'infos que ça, mais avec mes maigres connaissances:

      std::ios::app va écrire à partir de la fin du fichier, peu importe la "position" du caractère que tu lis. Peut être qu'il existe une manière de manipuler monflux ? Personnellement, avec ce que je sais, je stockerai le contenu du fichier dans une variable et je le manipulerai avec les outils fournis avec std::string, pour ensuite le réécrire dans le fichier.

      Mais si quelqu'un a mieux .. 😶

      • Partager sur Facebook
      • Partager sur Twitter
        8 juin 2023 à 14:45:32

        Un flux n'est pas un "tampon texte" d'une interface utilisateur, où ce que l'on tape s'insère à l'endroit du curseur (si on est en mode insertion)

        Y a pas de mode insertion. Le texte qu'on envoie se dépose à partir de l'endroit indiqué, en effaçant ce qui y est déjà.

        PS et la documentation https://cplusplus.com/reference/fstream/ofstream/ofstream/  dit, à propos des modes

        Flags describing the requested input/output mode for the file.
        This is an object of the bitmask member type<samp>openmode</samp>that consists of a combination of the following member constants:

        member constantstands foraccess
        <samp>in</samp> input File open for reading: the internal stream buffer supports input operations.
        <samp>out</samp>* output File open for writing: the internal stream buffer supports output operations.
        <samp>binary</samp> binary Operations are performed in binary mode rather than text.
        <samp>ate</samp> at end The output position starts at the end of the file.
        <samp>app</samp> append All output operations happen at the end of the file, appending to its existing contents.
        <samp>trunc</samp> truncate Any contents that existed in the file before it is open are discarded.

        Vérifions :

        • on envoie une série de trucs dans le flux de sortie
        •  on se positionne dedans
        • on envoie une chaine
        • on regarde
        Code:
        void ecriture() {
            const string nomFichier = "sortie.txt";
            ofstream sortie{nomFichier, ios_base::app}; // C++11
        
            sortie << "0123456789";
            sortie.seekp(ios_base::beg + 2);
            sortie << "COUCOU";
            sortie.close();
        }
        remarque : faut utiliser des tutoriels/cours qui ont moins de 10 ans, ça simplifie la vie, pas besoin de convertir, le constructeur accepte des strings pour le nom de fichier....
        Exécutons plusieurs fois
        $ ./prog ; cat sortie.txt
        0123456789COUCOU
        
        $ ./prog ; cat sortie.txt
        0123456789COUCOU0123456789COUCOU
        
        $ ./prog ; cat sortie.txt
        0123456789COUCOU0123456789COUCOU0123456789COUCOU
        Constatations
        • ça s'ajoute à la fin
        • A cause du mode app, chaque exécution allonge le fichier.
        Si on ne le met pas
             ofstream sortie{nomFichier};     // mode  out par défaut
        $ ./prog ; cat sortie.txt
        01COUCOU89

        le seekp est effectif et permet de revenir en arrière. Mais ça n'insère pas.



        -
        Edité par michelbillaud 8 juin 2023 à 21:35:19

        • Partager sur Facebook
        • Partager sur Twitter
          9 juin 2023 à 9:50:14

          Écrire en milieu de fichier c'est complexe car cela nécessite de déplacer le reste du contenu. En général du moment qu'un fichier ne fait pas des centaines de Mo, le plus simple reste de tout bufferiser dans une mémoire tampon, éditer puis tout écrire à nouveau.
          • Partager sur Facebook
          • Partager sur Twitter

          git is great because Linus did it, mercurial is better because he didn't.

            9 juin 2023 à 13:05:06

            La solution de facilité est d'utiliser un std::string pour le tampon en mémoire, vu qu'il y a des fonctions insert, replace etc.

            Mais si on en fait un usage intensif avec des gros tampons, ça va pas être idéal comme performances. Insérer ou remplacer, à tous les coups ça déménage tout ce qu'il y a dans le tampon après le point d'insertion.

            Si ça pose un problème, il faut se creuser pour trouver une structure de données plus adaptée.

            Autrefois, on faisait des trucs comme ça :  un grand tableau qui contient

            • au début du tableau : le début du contenu, jusqu'au point d'insertion
            • à la fin : la suite
            entre les deux, il y a donc un trou, où on met ce qu'on insère. Ce qui fait qu'on ne déplace rien, à part le pointeur vers le début du trou.
            En contrepartie, quand on bouge le point d'insertion, on déplace les trucs entre le début et la fin du tableau. There's no such thing as a free lunch.
            • Partager sur Facebook
            • Partager sur Twitter
              9 juin 2023 à 18:34:09

              Pas certain de te suivre michelbillaud.


              Je lis tout le fichier d'un seul bloc.


              Je saisis le texte à inséérer dans un autre "bloc" (string).


              J'écris le début jusqu'au point d'insertion, puis la partie saisie, puis la partie après le point d'insertion.


              Je n'ai rien inséré ni déplacé en mémoire.


              Bien sûr, je suis obligé de lire le fichier au complet et d'en écrire un autre au complet.

              • Partager sur Facebook
              • Partager sur Twitter

              Le Tout est souvent plus grand que la somme de ses parties.

                9 juin 2023 à 19:44:19

                En lecture écriture sur le même fichier :

                #include <fstream>
                #include <sstream>
                #include <string>
                
                int main()
                {
                    constexpr int pos = 7;
                    std::fstream file("scores.txt", std::ios::in | std::ios::out);
                    file.seekp(pos);
                    std::stringstream stream;
                    stream << file.rdbuf();
                    file.seekp(pos);
                    file << " tout le monde";
                    file << stream.rdbuf();
                
                    return 0;
                }

                -
                Edité par rouIoude 9 juin 2023 à 21:00:43

                • Partager sur Facebook
                • Partager sur Twitter
                ...
                  10 juin 2023 à 14:31:04

                  PierrotLeFou a écrit:

                  Pas certain de te suivre michelbillaud.


                  Je saisis le texte à inséérer dans un autre "bloc" (string).


                  J'écris le début jusqu'au point d'insertion, puis la partie saisie, puis la partie après le point d'insertion.


                  Je n'ai rien inséré ni déplacé en mémoire.



                  Tu n'inseres pas dans une structure de donnees existante. Tu construis une autre structure, une copie, a partir de début du texte, du truc à ajouter et de la suite.

                  Si c'est pour mettre le résultat dans le fichier que tu as lu, ça va tout copier.

                  De mon côté, je parlais des tampons pour lesquels l'opération fréquente  (privilegiée) est d'insérer à l'endroit du "curseur"



                  • Partager sur Facebook
                  • Partager sur Twitter
                    12 juin 2023 à 11:30:35

                    Salut,

                    Avec les fichiers, il n'y pas 36 solutions, et sauf si ton fichiers fait des centaines de Mo, le plus simple est encore de monter toutes tes données en mémoire, les mettre à jour, et les réécrire.

                    Point d'attention:
                    Si la quantité de données à réécrire est inférieur à la quantité lue, il te faudra:
                    1) Fermer le fichier (de toutes façons, garder un fichier ouvert trop longtemps n'est pas une bonne idée).
                    2) Supprimer le fichier.
                    3) Le réécrire.
                    Et ce pour la simple raison que l'on ne sais pas "diminuer" la taille d'un fichier.

                    • Partager sur Facebook
                    • Partager sur Twitter
                      12 juin 2023 à 11:53:19

                      Si c'est des grosses données on peut aussi manipuler une structure plus complexe qui combine

                      • des tampons en mémoire
                      • des intervalles du fichier d'origine.

                      par exemple on dira que le texte est composé
                      • des caractères d'indice 0 à 7 du fichier
                      • de la chaîne "tout le monde"
                      • des caractères 8 à la fin du fichier
                      et réarranger le fichier à la fin en le "mappant" en mémoire (ça devient un tableau de caractères dans l'espace mémoire virtuel, grâce au bidouillage de la table des pages), et en procédant de façon à minimiser les transferts. La il faut redimensionner, décaler la fin, et copier la chaîne au bon endroit.

                      Mais enfin, ça ne correspond pas aux besoins de l'OP qui visiblement essaie juste de caser les différents appels de fonction pour voir ce que ça donne, sans but établi.


                      • Partager sur Facebook
                      • Partager sur Twitter

                      Ecriture au milieu d'un fichier .txt

                      × 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.
                      • Editeur
                      • Markdown