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

C++ Discussion :

détecter la fin d'un fichier texte


Sujet :

C++

  1. #1
    Membre averti

    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    333
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 333
    Points : 411
    Points
    411
    Billets dans le blog
    15
    Par défaut détecter la fin d'un fichier texte
    Bonjour,

    comment détecte-t-on la fin d'un fichier texte?

    une idée?

  2. #2
    Membre averti

    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    333
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 333
    Points : 411
    Points
    411
    Billets dans le blog
    15
    Par défaut
    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::string readFileIntoString(const std::string path) {
      if (!entree.is_open()){
        std::cerr << "Could not open the file - '" << path << "'" << std::endl;
        exit(1);
      }
      else{
        return std::string((std::istreambuf_iterator<char>(entree)),
    		       std::istreambuf_iterator<char>());
      }
    }
    int main(){
       string fichier=readFileIntoString(path);
       taille=fichier.size();
       /*puis, la variable qui indice fichier ne doit pas être supérieur à taille*/
    }
    qu'en pensez-vous?

  3. #3
    Membre expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    742
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2011
    Messages : 742
    Points : 3 641
    Points
    3 641
    Par défaut
    Tout dépend des APIs utilisées. Il y en principalement 2:

    La première utilise le concept "eof" qui retourne un entier (int_type) représentant un caractère (char_type) ou EOF. Par conséquent, sizeof(int_type) est supérieur à sizeof(char_type) et EOF n'est pas représentable dans un char_type. La manière usuelle de lire est la suivante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int_type result;
    while (EOF != (result = stream.getc())) {
      char_type ch = int_to_char(result); // qui n'est qu'un simple cast
      // ...
    }
    Là, on suppose une API caractère par caractère. Quand on utilise un mode bloc, on passe un buffer et il y a une api style is_eof() pour savoir si on est à la fin ou non. EOF n'est pas la seule fin possible, il y a aussi les erreurs (corruption de fichier, etc), mais qui seront souvent gérées à part avec une valeur EOF représentant tous les cas d'erreurs.

    Cela représente le comportement de FILE ou de std::streambuf. Pour std::istream, les fonctions retournent plutôt des booléens et il faut regarder rdstate()/is_eof().

    Le second type d'API utilise le concept de peut lire, mais rien à lire. On demande de remplir un buffer et si 0 octet et lu, alors c'est la fin du fichier. C'est le fonctionnement d'une majorité — voir toutes — les APIs système (ex: read/write).

    Avec ton exemple utilisant std::istreambuf_iterator, la détection se ferra avec entree.is_eof() (qui comme dit précédemment n'est pas la seule chose qui interrompe la lecture).

    Mais si la question est comment lire efficacement un fichier ? On peut répondre en n'utilisant pas std::istreambuf_iterator .

    Les itérateurs sur flux, c'est bien sympathique, mais c'est la méthode la plus lente. Il vaut mieux au moins faire des lectures par bloc et pré-allouer un buffer de la taille du fichier (avec std::filesystem::file_size() et string::reserve()/resize() en fonction de comment on s'y prend). L'idéal étant d'aligner la mémoire à la taille d'une page système, mais il faut un autre type que std::string (ou un autre allocateur).

    On peut aussi ne pas lire le fichier complet et travailler avec un bloc de taille fixe.

    Et si on veut vraiment être rapide (surtout pour les gros fichiers), on map un fichier en mémoire (mmap / CreateFileMapping).

  4. #4
    Membre averti

    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    333
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 333
    Points : 411
    Points
    411
    Billets dans le blog
    15
    Par défaut
    Peux-tu me donner quelques exemples commentés?

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

    Informations professionnelles :
    Activité : aucun

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

    En fait, si tu utilise un fichier sous la forme d'un flux (comme ifstream ou ofstream), il faut savoir que les objets de ce type sont implicitement convertibles en booléen.

    Pour faire simple, tant que tu obtiens true en les testant même d'une manière aussi barbare que [/c]if(monFluxDeFichier)[/c], c'est que ton flux est dans un état valide et prêt pour l'opération (de lecture ou d'écriture, selon le cas) suivante.

    Alors, il y a -- effectivement -- des tonnes de raisons qui font que ton flux serait converti à false pour représenter un état invalide lors d'un de ces tests. Parmis lesquelles on retrouve, entre autre, le fait que la fin de fichier a été atteinte.

    Cela signifie donc que tu risques d'avoir d'autres raisons que la fin de fichiers, mais, basiquement, un code proche de
    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
    17
    18
    19
    20
    21
    22
    23
    24
    25
    int main(){
        std::ifstream ifs("monFichieer.txt"); //ouvre automatiquement le fichier indiqué
        if(!ifs) { // oups, le fichier n'a pas pu être ouvert
            throw std::runtime_error("unable to open the file"); // ca ne sert à rien d'essayer d'aller plus loin
        }
        /* C'est un fichier texte, je veux en récupérer les lignes une à une
         * je les récupérerai dans une chaine de caractères
         */
        std::string temp;
        /* et je les placerai dans un tableau de chaines de caractères (pour utilisation ultérieure) */
        std::vector<std::string> content.
        while(ifs) { // tant que le fichier est dans un état valide
            /* j'extrait du fichier tout ce qui précède le premier retour à la ligne
             */
           std::getline(ifs, temp);
           /* et je rajoute le résultat à mon tableau */
           content.push_back(temp);
        }
        /* Quand on arrive ici, le flux est dans un état invalide
        * sans doute parce que l'on a atteint la fin de fichier,
        * mais *** peut etre *** pour une autre raison
         */
     
        /* ... */
    }
    fera sans doute parfaitement l'affaire dans la plupart des situations.

    Après, on peut appeler la fonction membre good() qui renverra true si le flux est dans un état valide, et qui a donc un comportement tout à fait similaire à la convertion implicite
    Ou l'on peut également tester si le flux se trouve dans un état invalide bien particulier au travers des fonctions membres eof(), fail() et bad().

    Il faut cependant noter que ces fonctions ( eof(), fail() et bad() ) ne renvoie true que lorsque l'erreur est déjà survenue, et donc que le flux est déjà dans un état invalide.
    un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    while( ! ifs.eof()){
        /* j'essaye d'extraire des données ici */
    }
    reste donc potentiellement dangereux parce que
    1. on risque d'avoir déjà dépassé la fin de fichier avant que l'appel à eof ne renvoie true et
    2. on ne teste qu'un seul état sur trois qui soit susceptible d'indiquer que le fichier est devenu invalide

    Il y a donc de gros risques qu'une dernière extraction soit tentée, alors que le flux est déjà dans un état invalide, avant que l'on ne se rende compte que c'est le cas... Ce qui forcera le flux à lancer une exception, qui risque de faire planter le programme...
    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

  6. #6
    Membre expérimenté
    Femme Profil pro
    ..
    Inscrit en
    Décembre 2019
    Messages
    585
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 94
    Localisation : Autre

    Informations professionnelles :
    Activité : ..

    Informations forums :
    Inscription : Décembre 2019
    Messages : 585
    Points : 1 310
    Points
    1 310
    Par défaut
    Salut,

    Comme eof() et fail() vont généralement de pair, il suffit, en fin d'opération, de valider le test if (file.eof() && ! file.bad()) pour avoir l'assurance que le fichier a été parcouru dans sa totalité.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 626
    Points : 30 684
    Points
    30 684
    Par défaut
    Citation Envoyé par kaitlyn Voir le message
    Salut,

    Comme eof() et fail() vont généralement de pair, il suffit, en fin d'opération, de valider le test if (file.eof() && ! file.bad()) pour avoir l'assurance que le fichier a été parcouru dans sa totalité.
    En fait, eof() va de pair avec fail(), dans le sens où, si eof() renvoie true, fail() le fera aussi.

    Par contre, l'inverse n'est pas forcément vrai : fail() peut renvoyer true, parce que "quelque chose" s'est mal passé lors de l'extraction précédante, alors que eof() renvoie false, parce que ce n'était pas, techniquement parlant,la fin de fichier
    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

  8. #8
    Membre expérimenté
    Femme Profil pro
    ..
    Inscrit en
    Décembre 2019
    Messages
    585
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 94
    Localisation : Autre

    Informations professionnelles :
    Activité : ..

    Informations forums :
    Inscription : Décembre 2019
    Messages : 585
    Points : 1 310
    Points
    1 310
    Par défaut
    Salut,

    Tu fais bien de paraphraser, ce n'était peut-être pas assez clair.

  9. #9
    Membre averti

    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    333
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 333
    Points : 411
    Points
    411
    Billets dans le blog
    15
    Par défaut
    @deedolith m'a conseillé de charger tout le fichier, le traiter, puis enregistrer le résultat, si besoin.
    est-ce un bon conseil?

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 626
    Points : 30 684
    Points
    30 684
    Par défaut
    Citation Envoyé par emmesse Voir le message
    @deedolith m'a conseillé de charger tout le fichier, le traiter, puis enregistrer le résultat, si besoin.
    est-ce un bon conseil?
    Disons que cela permet de garder le fichier ouvert moins longtemps, avec tous les avantages que cela comporte (entre autre, le fait qu'il soit disponible pour d'autres systèmes qui tenteraient de le mettre à jour)

    Ensuite, cela permet de clairement séparer les différentes étapes et donc, cela permet d'éviter d'essayer d'écrire dans un fichier qui est ouvert ... en lecture.

    Enfin, cela a l'avantage de séparer clairement les différents problèmes, et donc, de simplifier la "logique" du traitement, ce qui est et sera toujours une bonne chose : ce n'est pas pour rien que le premier principe mis en avant par les principes SOLID est ... le SRP (Single responsibility Principle, ou principe de la responsabilité unique).

    On peut donc dire que, dans l'absolu, c'est un excellent conseil et que tu as sans doute tout intérêt à le respecter.

    Cependant, l'informatique est toujours une question de nuances, pour lesquelles il y a très peu de "vérités absolues" en dehors des lois ampiriques (qui, elles, resteront toujours vraies, remarque) : Il sera en effet toujours possible de trouver "LA circonstance particulière" dans laquelle la règle absolue ne sera pas applicable, et il faudra donc ... "faire avec".

    Au final, la réponse se doit d'être : "dans l'absolu, oui, mais fais attentions aux circonstances particulières"
    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

  11. #11
    Membre averti

    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    333
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 333
    Points : 411
    Points
    411
    Billets dans le blog
    15
    Par défaut
    Merci de m'avoir répondu

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Fin d'un fichier texte
    Par jmini dans le forum Shell et commandes GNU
    Réponses: 8
    Dernier message: 20/10/2009, 16h53
  2. Ecrire à la fin d'un fichier texte
    Par Super_babar dans le forum Fortran
    Réponses: 2
    Dernier message: 10/04/2009, 16h33
  3. Ecriture à la fin d'un fichier texte
    Par Charly910 dans le forum Langage
    Réponses: 3
    Dernier message: 09/02/2009, 19h35
  4. Réponses: 19
    Dernier message: 10/07/2007, 09h24
  5. J2ME et écriture à la fin d'un fichier texte
    Par mattthieu dans le forum Java ME
    Réponses: 3
    Dernier message: 08/06/2007, 13h14

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