IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage C++ Discussion :

Souci de lecture de fichier


Sujet :

Langage C++

  1. #1
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2009
    Messages : 6
    Points : 1
    Points
    1
    Par défaut Souci de lecture de fichier
    Bonjour à tous.

    Je me remets actuellement au C++, et je dois notamment lire le contenu d'un fichier. J'ai lu pas mal de forums dont celui-ci, et j'ai testé deux méthodes, mais je rencontre dans les deux cas le même problème. Voici le code de ma fonction posant problème:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    {
    ifstream fichier( "test.txt" );
    stringstream buffer;
    buffer << fichier.rdbuf();
    fichier.close();
    }
    Et voici l'exemple de fichier test.txt que j'utilise:
    abc;fg
    1;2
    4
    Le souci que je rencontre est le suivant:

    En exécutant en mode debug, avec un point d'arrête au niveau de fichier.close, je me retrouve avec dans buffer le contenu suivant:

    abc;fg
    1;2
    4ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍýýýý««««««««îþîþ
    J'ai également eu un buffer avec un contenu de ce genre en utilisant des CFile et CString pour lire le fichier, et je ne comprends pas du tout d'où ça peut venir.

    Merci d'avance pour votre aide.

  2. #2
    Membre confirmé Avatar de Lavock
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    560
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 560
    Points : 633
    Points
    633
    Par défaut
    J'en suis pas sur, mais je dirai que le rdbuf place tout le contenu du buffer. Y compris les cases "vides" (POD). Donc c'est une mauvaise idée de faire du << sur un streambuff...

    Deuxième solution, as-tu pensé à assuré une ligne vide à la fin de ton fichier ?
    The mark of the immature man is that he wants to die nobly for a cause, while the mark of the mature man is that he wants to live humbly for one.
    --Wilhelm Stekel

  3. #3
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2009
    Messages : 6
    Points : 1
    Points
    1
    Par défaut
    Je sais pas si ça vient du rdbuf et de <<, vu que j'avais le même problème avec un code du style

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    {
    CFile *fichier = NULL;
     
    fichier = new CFile();
    fichier->Open(("test.txt"), CFile::modeRead | CFile::shareDenyNone, NULL);
    int taille= fichier->GetLength();
    char *buffer = new char[taille];
     
    fichier->Read(buffer, taille);
    fichier->Close();
    }
    Concernant la ligne vide à la fin du fichier, j'ai réessayé en sautant des lignes après le dernier caractère, ça n'a rien changé, est-ce que c'est de ça que tu parlais?

    Merci.

  4. #4
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,
    Le problème avec la version MFC c'est que ton tableau de char n'a pas de '\0'. Donc tu ne peux l'utiliser comme une chaîne de caractère.
    [EDIT] : au pire tu aurais du faire comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    {
    CFile *fichier = NULL;
     
    fichier = new CFile();
    fichier->Open(("test.txt"), CFile::modeRead | CFile::shareDenyNone, NULL);
    int taille= fichier->GetLength();
    char *buffer = new char[taille+1];
     
    taille = fichier->Read(buffer, taille);
    buffer[taille] = 0;
    fichier->Close();
    }
    Avec la version STL et les streams, comment détermines-tu le contenu de buffer ? Peux-tu montrer le code ?

  5. #5
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2009
    Messages : 6
    Points : 1
    Points
    1
    Par défaut
    Désolé pour les balises pour le code, j'avais cherché mais apparemment pas assez.

    D'après ce que m'a dit un collègue, j'avais mal géré la fin du fichier.
    Donc j'ai rajouté un saut de ligne '\n' suivi d'un 'E' dans le fichier, et j'ai utilisé AfxExtractSubString avec '\nE' comme délimiteur. Résultat, ça marche. Par contre je sais pas si c'est très propre.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    {
    CFile *fichier = NULL;
     
    fichier = new CFile();
    fichier->Open(("test.txt"), CFile::modeRead | CFile::shareDenyNone, NULL);
    int taille= fichier->GetLength();
    char *buffer = new char[taille];
     
    fichier->Read(buffer, taille);
    fichier->Close();
     
    CString buffer1=CString(buffer);
    CString buffer2;
    AfxExtractSubString(buffer2,buffer1,0, '\nE');
    }
    Je n'ai pas très bien compris la question sur le contenu de buffer, tout est dans ce que j'ai posté (code et contenu du fichier).

  6. #6
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    1/A mon avis ta version MFC souffre toujours du problème que tu injectes dans buffer1 un char* qui ne se termine pas par '0'. Tu devrais utiliser taille+1 et forcer buffer[taille] à 0. Au fait, il manque le delete[]buffer.

    2/Pour la version STL, tu dis que le contenu de buffer est
    abc;fg
    1;2
    4ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍýýýý««««««««îþîþ
    Comment le sais-tu ?

  7. #7
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2009
    Messages : 6
    Points : 1
    Points
    1
    Par défaut
    C'est noté pour le /1.

    Pour le /2, je me mets en mode debug avec un point de passage après que buffer soit rempli, et (sous Visual Studio) je vais voir les valeurs de la variable.

    Merci pour l'aide!

  8. #8
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Taklok Voir le message
    Pour le /2, je me mets en mode debug avec un point de passage après que buffer soit rempli, et (sous Visual Studio) je vais voir les valeurs de la variable.
    Il ne faut pas te fier à la valeur vue depuis le debugger. Un stringstream n'est pas une chaîne de caractère à la C terminée par 0. C'est un couple buffer/taille. Donc s'il n'y a pas de '\0' à la fin de tes données, le debugger t'affiche ce qu'il y a en mémoire à la suite des données. Mais, la classe stringstream en se basant sur une taille ne te retournera pas quelque chose d'invalide.
    Pour preuve tu peux tester ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    {
        std::ifstream fic("fichier.txt");
        std::stringstream buffer;
        buffer << fic.rdbuf();
        fic.close();
        {
            char cline[255];
            int icount(0);
            while(buffer.getline(cline,255)){
                std::cout<<"Ligne "<<icount<<" : ";
                std::cout<<cline<<std::endl;
                ++icount;
            }
        }
    }
    Une question si tu me permets : pourquoi projeter les donner de ton fichier intégralement dans une chaîne de caractère ? Ce n'est pas pour résoudre un problème de perf au -.

  9. #9
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2009
    Messages : 6
    Points : 1
    Points
    1
    Par défaut
    Je vois le problème alors, si j'ai bien compris il suffit de contrôler proprement la fin du fichier.

    J'inscris mon fichier dans une chaine de caractère, car je dois entrer les données du fichier dans un tableau de base de données assez complexes, et c'est le moyen le plus pratique que j'aie trouvé.

  10. #10
    Membre confirmé Avatar de Lavock
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    560
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 560
    Points : 633
    Points
    633
    Par défaut
    Citation Envoyé par Taklok Voir le message
    Je vois le problème alors, si j'ai bien compris il suffit de contrôler proprement la fin du fichier.
    Non, soit tu rajoutes un '\0' à la fin de ta chaine (dans ton prog), soit tu utilise getline pour une lecture ligne par ligne.
    The mark of the immature man is that he wants to die nobly for a cause, while the mark of the mature man is that he wants to live humbly for one.
    --Wilhelm Stekel

  11. #11
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Lavock Voir le message
    Non, soit tu rajoutes un '\0' à la fin de ta chaine (dans ton prog), soit tu utilise getline pour une lecture ligne par ligne.
    Il me semble qu'une fois le stringstream initialisé avec le buffer du flux, il faut utiliser le stringstream sans plus se soucier du \0. Comme avec un flux normal. Tu auras un eof quand les données seront épuisées, non ?

  12. #12
    Membre confirmé Avatar de Lavock
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    560
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 560
    Points : 633
    Points
    633
    Par défaut
    Le problème c'est l'initialisation, du à :

    The streambuf version copies as many characters as possible from the stream buffer object used as right-hand parameter, either until an error happens or until there are no more characters to copy.
    Le truc, c'est qu'un streambuffer c'est un peu POD selon les cas... Je me suis jamais posé la question jusque là, mais je vois pas trop comment récupéré un stringstream exploitable depuis un streambuffer...
    Peut-être en utilisant streambuf * io::rdbuf (streambuff *). Mais je garantie pas non plus le fonctionnement.
    The mark of the immature man is that he wants to die nobly for a cause, while the mark of the mature man is that he wants to live humbly for one.
    --Wilhelm Stekel

  13. #13
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    A vrai dire, je ne suis pas loin de penser que la décision de charger ton fichier dans un buffer (que tu considérera, qui plus est, comme un tableau C style de caractères) n'est franchement pas la meilleure des solutions que tu pourrais envisager...

    Si l'on se base sur le principe (qui semble émerger de ton exemple de fichier) d'un fichier de type "csv" où chaque ligne correspond à une ligne du tableur et ou chaque valeur correspond à une cellule de tableur, pourquoi ne pas agir en conséquence en travaillant de manière la plus logique possible, à savoir:
    récupérer chaque ligne du fichier séparément à l'aide d'un "simple" boucle prenant la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    std::string temp;
    std::ifstream ifs("lefichier.txt");
    while(std::getline(ifs,temp))
    {
    }
    dans laquelle:
    1. tu crées la ligne de tableur nécessaire (ou tu la sélectionne, selon le cas)
    2. tu récupère chaque valeur de cellule séparément et, pour chaque valeur récupérée
      1. tu crée la cellule nécessaire (ou tu la sélectionne, selon le cas)
      2. tu place la valeur récupérée dans la cellule nouvellement créée / sélectionnée
    Si tu dispose de boost, un petit coup de boost::tokenizer pourrait faire le travail pour toi, autrement, il peut exister plusieurs solutions en fonction du type de données que ton tableur peut attendre (sous la forme de chaine de caractères ou de valeurs numériques )
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  14. #14
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Lavock Voir le message
    Le truc, c'est qu'un streambuffer c'est un peu POD selon les cas... Je me suis jamais posé la question jusque là, mais je vois pas trop comment récupéré un stringstream exploitable depuis un streambuffer...
    Peut-être en utilisant streambuf * io::rdbuf (streambuff *). Mais je garantie pas non plus le fonctionnement.
    Je n'ai pas non plus trop creusé la question, mais il existe une surcharge de l'opérateur << pour un streambuffer. Et un streambuffer sait (enfin peut savoir) quel est le nombre d'octets (enfin de charactères) qu'il contient avant d'atteindre le EOF. Donc, à priori, je ne vois pas de problème.

  15. #15
    Membre confirmé Avatar de Lavock
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    560
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 560
    Points : 633
    Points
    633
    Par défaut
    Ben justement, ma quote vient d'un commentaire sur l'opérateur ostream::operator<<(streambuf*).

    Donc oui, le streambuffer sait... Mais dans la copie à un ostream, il a l'aire de faire plus bourin >< ! A vérifier tous ça !
    The mark of the immature man is that he wants to die nobly for a cause, while the mark of the mature man is that he wants to live humbly for one.
    --Wilhelm Stekel

  16. #16
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2009
    Messages : 6
    Points : 1
    Points
    1
    Par défaut
    Merci pour vos réponses, le temps presse au niveau de mon projet donc je vais opter pour la démarche que j'ai exposée précédemment, et qui me semble fonctionnelle d'après mes tests, bien que pas forcément la plus propre.

  17. #17
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par Taklok Voir le message
    Merci pour vos réponses, le temps presse au niveau de mon projet donc je vais opter pour la démarche que j'ai exposée précédemment, et qui me semble fonctionnelle d'après mes tests, bien que pas forcément la plus propre.
    Le fait est que, selon moi, la solution la plus simple est toujours la moins compliquée... heuu, pardon, la meilleure, et que, bien souvent, on perd beaucoup moins de temps à "abandonner" une solution par trop complexe au profit d'une solution plus simple qu'à essayer, "contre vents et marées", de faire fonctionner la solution complexe que l'on avait envisagée au début.

    Maintenant, ce n'est qu'un avis personnelle, mais je suis d'accord avec moi sur ce point
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

Discussions similaires

  1. Souci de lecture sur des fichiers
    Par clojo dans le forum MATLAB
    Réponses: 4
    Dernier message: 10/03/2013, 18h43
  2. Souci de lecture du fichier XML
    Par cadeau10 dans le forum Android
    Réponses: 3
    Dernier message: 12/05/2011, 15h41
  3. Soucis avec lecture d'un Boolean dans un fichier property
    Par timbrochier dans le forum Langage
    Réponses: 2
    Dernier message: 01/10/2010, 18h28
  4. quelques soucis de lecture de fichiers avec fscanf
    Par monsieurab dans le forum Bibliothèque standard
    Réponses: 2
    Dernier message: 05/11/2008, 14h28
  5. Lecture de fichiers ".WAV"...
    Par 0x4e84 dans le forum Langage
    Réponses: 2
    Dernier message: 03/09/2002, 09h43

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo