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++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé

    Homme Profil pro
    développeur à la maison
    Inscrit en
    Septembre 2006
    Messages
    391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn et Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : développeur à la maison

    Informations forums :
    Inscription : Septembre 2006
    Messages : 391
    Billets dans le blog
    16
    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 éclairé

    Homme Profil pro
    développeur à la maison
    Inscrit en
    Septembre 2006
    Messages
    391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn et Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : développeur à la maison

    Informations forums :
    Inscription : Septembre 2006
    Messages : 391
    Billets dans le blog
    16
    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
    750
    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 : 750
    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 éclairé

    Homme Profil pro
    développeur à la maison
    Inscrit en
    Septembre 2006
    Messages
    391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn et Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : développeur à la maison

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

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 633
    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 Expert
    Femme Profil pro
    ..
    Inscrit en
    Décembre 2019
    Messages
    667
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 95
    Localisation : Autre

    Informations professionnelles :
    Activité : ..

    Informations forums :
    Inscription : Décembre 2019
    Messages : 667
    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é.

+ 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