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 :

Lecture de fichier par blocs


Sujet :

C++

  1. #1
    Membre habitué Avatar de nicolas66
    Profil pro
    Étudiant
    Inscrit en
    Février 2004
    Messages
    326
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2004
    Messages : 326
    Points : 146
    Points
    146
    Par défaut Lecture de fichier par blocs
    Bonjour,

    Dans le cadre d'un projet, je dois écrire un programme C++ pour lire un fichier par blocs de 9 caractères. J'ai trouvé la solution suivante :

    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
    26
    27
     
    #include <iostream>
    #include <fstream>
    #include <cstdlib>
    #include <cstdio>
     
     
    int main( int argc, char ** argv )
    {
    	std::ifstream Input("file.txt");
     
    	if( !Input )
    		return EXIT_FAILURE;
     
    	char Block[10];
     
    	while( Input.good() )
    	{
    		memset(Block, 0, 10);
    		Input.read(Block, 9);
    		std::cout << Block << std::endl;
    	}
     
    	Input.close();
     
    	return EXIT_SUCCESS;
    }
    Cette solution a l'air de bien fonctionner. Cependant, je voudrai avoir votre avis sur d'éventuelles erreurs et si quelqu'un aurait une solution plus élégante à me proposer en utilisant par exemple la STL de manière plus efficace. Merci d'avance


    Nico.
    Athlon 6000+ Dual Core & GeForce 8600 GT -- Ubuntu Gutsy

  2. #2
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    * Ben .. la boucle de lecture est incorrecte. good, ce n'est pas mieux qu'eof !
    * Les constantes magiques, c'est rarement conseillé.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    const int BLOCK_SIZE = 9;
    char block[BLOCK_SIZE + 1] = {0};
    //     +1 => feinte pour le 0 terminal utilisé par le cout, sans intérêt autrement
    while( input.read(block, BLOCK_SIZE ) )
    {
        std::cout << block << std::endl;
    }
    Il faudrait rajouter des tests pour savoir quelle quantité de données a vraiment été lue. => readsome()

    NB: en général, les Majuscules sont réservées aux types en C&C++.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  3. #3
    Membre habitué Avatar de nicolas66
    Profil pro
    Étudiant
    Inscrit en
    Février 2004
    Messages
    326
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2004
    Messages : 326
    Points : 146
    Points
    146
    Par défaut
    - En fait j'ai commencé par la version que tu m'as filé en mettant l'appel à la fonction read directement dans le test du while. Cependant, je me trouve face à un problème : le dernier bloc est inférieur à 9 caractères et le bloc est zappé. J'ai donc temporairement changé la structure de la boucle en faisant appel à la fonction good.

    - Concernant les nombres magiques, ils le sont simplement dans l'exemple ci-dessus, pas dans mon programme.

    Pour le reste, je prends note . Sinon, n'y aurait-il pas moyen de mieux utiliser la STL ?
    Athlon 6000+ Dual Core & GeForce 8600 GT -- Ubuntu Gutsy

  4. #4
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    Et donc, tu ne vas pas correctement lire la fin de ton fichier. good, contrairement à ce que son nom pourrait nous faire croire, ce n'est pas si bon que cela.
    => readsome.

    Ici, on n'utilise pas la STL -- les flux sont dans la SL, pas la STL.
    Sinon,
    - il y a un très bon bouquin de Kreft et Langer sur les flux
    - 9, c'est pas tip-top efficace pour une lecture bufferisée
    - il y a une autre solution qui consiste à taper directement dans les streambuf. Jean Marc en parlait dans un autre fil ces jours-ci. Le fil sur l'unicode peut-être ?
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  5. #5
    Membre habitué Avatar de nicolas66
    Profil pro
    Étudiant
    Inscrit en
    Février 2004
    Messages
    326
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2004
    Messages : 326
    Points : 146
    Points
    146
    Par défaut
    Et donc, tu ne vas pas correctement lire la fin de ton fichier. good, contrairement à ce que son nom pourrait nous faire croire, ce n'est pas si bon que cela.
    => readsome.
    Je suis au courant que good n'est pas la panacée. Je l'ai utilisé car je ne parvenais pas au résultat sans l'utiliser. Mais comment se fait-il alors que cela fonctionne dans mon cas ?

    Pour le reste, je vais essayer de me renseigner
    Athlon 6000+ Dual Core & GeForce 8600 GT -- Ubuntu Gutsy

  6. #6
    Inactif  

    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    534
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 534
    Points : 403
    Points
    403
    Par défaut
    Bonjour,

    Voiçi de l' info qui me paraît obscure :
    Unformatted Input Functions
    All the unformatted input functions have some common behavior. Each starts by constructing a temporary object of type std::basic_istream::sentry with the second argument (noskipws) set to true. This has several effects, concluding with the setting of a status flag; see the sentry documentation for more.

    If the sentry status is good, the function tries to extract whatever data is appropriate for the type of the argument.

    The number of characters extracted is stored for later retrieval by gcount().

    If an exception is thrown during extraction, ios_base::badbit will be turned on in the stream's error state without causing an ios_base::failure to be thrown. The original exception will then be rethrown.

    * __istream_type & get (__streambuf_type &__sb)
    * __istream_type & get (__streambuf_type &__sb, char_type __delim)
    * __istream_type & get (char_type *__s, streamsize __n)
    * __istream_type & get (char_type *__s, streamsize __n, char_type __delim)
    * __istream_type & get (char_type &__c)
    * int_type get ()
    * __istream_type & getline (char_type *__s, streamsize __n)
    * __istream_type & getline (char_type *__s, streamsize __n, char_type __delim)
    * __istream_type & ignore (streamsize __n, int_type __delim)
    * __istream_type & ignore (streamsize __n)
    * __istream_type & ignore ()
    * int_type peek ()
    * __istream_type & putback (char_type __c)
    * __istream_type & read (char_type *__s, streamsize __n)
    * streamsize readsome (char_type *__s, streamsize __n)
    * __istream_type & seekg (off_type, ios_base::seekdir)
    * __istream_type & seekg (pos_type)
    * int sync ()
    * pos_type tellg ()
    * __istream_type & unget ()

    * operator void * () const
    * bool operator! () const
    A vrai dire je ne sais pas ce que renvoit __istream_type ?
    J' ai cherché sa définition, mais sans succés...

    Salut.

  7. #7
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    Citation Envoyé par nicolas66
    Mais comment se fait-il alors que cela fonctionne dans mon cas ?
    Va vite jouer au loto.
    Si le read foire, le contenu du buffer est à priori indéterminé. Or on ne peut pas savoir si il foire sans tester le flux après lecture.
    Je trouve surprenant que tu obtiennes tes n (!=9) derniers caractères suivis d'un 0-terminal.

    Citation Envoyé par dj.motte
    A vrai dire je ne sais pas ce que renvoit __istream_type ?
    Double underscore en préfixe ? C'est une spécificité d'implémentation propre à la bibliothèque dont tu as trouvé cet extrait de documentation. Il s'agit très probablement d'un alias ou équivalent au std::istream manipulé.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  8. #8
    Membre habitué Avatar de nicolas66
    Profil pro
    Étudiant
    Inscrit en
    Février 2004
    Messages
    326
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2004
    Messages : 326
    Points : 146
    Points
    146
    Par défaut
    Bon, j'ai essayé de prendre en compte tes remarques :

    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
     
    #include <iostream>
    #include <fstream>
    #include <cstdlib>
     
     
    int main( int argc, char ** argv )
    {
    	std::ifstream Input("crypto.txt");
     
    	if( !Input )
    		return EXIT_FAILURE;
     
    	char Block[10] = {0};
     
    	while( Input.readsome(Block, 9) )
    	{
    		std::cout << Block << std::endl;
    		memset(Block, 0, 10);
    	}
     
    	Input.close();
     
    	return EXIT_SUCCESS;
    }
    Athlon 6000+ Dual Core & GeForce 8600 GT -- Ubuntu Gutsy

  9. #9
    Inactif  

    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    534
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 534
    Points : 403
    Points
    403
    Par défaut
    Bonjour,

    Luc Hermitte écrit :
    Double underscore en préfixe ? C'est une spécificité d'implémentation propre à la bibliothèque dont tu as trouvé cet extrait de documentation. Il s'agit très probablement d'un alias ou équivalent au std::istream manipulé.
    Cher ami, vous ne répondez pas à la question. Double souligné en préfixe, ce n' est qu' une broutille dans l' obscurantisme linguistique...
    Maintenant pour revenir au sujet __istream_type c' est quoi au juste ? Une façon de signifier quelque chose, mais quoi ?
    SVP ne me dîtes pas que c' est moi qui ai manipulé cette syntaxe, qui s' exhibe dans la documentation officielle du C++ !

    Salut.

  10. #10
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Bien cher condisciple, interpellé par votre interrogation, j'ai regardé la seule documentation qui ait un caractère officiel du C++, à savoir les Saintes Écritures du Standard Iso, et je suis en mesure de vous affirmer que les termes impies de "__istream_type" n'y sont jamais évoqués.

    Le plus proche que j'ai pu trouver de votre prose païenne, c'est :
    Citation Envoyé par Le standard, verset 27.6.1
    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
    // 27.6.1.3 Unformatted input:
    streamsize gcount() const;
    int_type get();
    basic_istream<charT,traits>& get(char_type& c);
    basic_istream<charT,traits>& get(char_type* s, streamsize n);
    basic_istream<charT,traits>& get(char_type* s, streamsize n,
    char_type delim);
    basic_istream<charT,traits>& get(basic_streambuf<char_type,traits>& sb);
    basic_istream<charT,traits>& get(basic_streambuf<char_type,traits>& sb,
    char_type delim);
    basic_istream<charT,traits>& getline(char_type* s, streamsize n);
    basic_istream<charT,traits>& getline(char_type* s, streamsize n,
    char_type delim);
    basic_istream<charT,traits>& ignore
    (streamsize n = 1, int_type delim = traits::eof());
    int_type peek();
    basic_istream<charT,traits>& read (char_type* s, streamsize n);
    streamsize readsome(char_type* s, streamsize n);
    basic_istream<charT,traits>& putback(char_type c);
    basic_istream<charT,traits>& unget();
    int sync();
    pos_type tellg();
    basic_istream<charT,traits>& seekg(pos_type);
    basic_istream<charT,traits>& seekg(off_type, ios_base::seekdir);
    Avec comme définition préalable :
    Citation Envoyé par Le standard, verset 27.6.1
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    template <class charT, class traits = char_traits<charT> >
    class basic_istream
    Donc, cet __istream_type n'est qu'un type interne, défini pour les besoins d'une implémentation. Comme l'a cité Luc :
    Citation Envoyé par Luc Hermitte
    Il s'agit très probablement d'un alias ou équivalent au std::istream manipulé.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  11. #11
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par Luc Hermitte
    Et donc, tu ne vas pas correctement lire la fin de ton fichier. good, contrairement à ce que son nom pourrait nous faire croire, ce n'est pas si bon que cela.
    => readsome.
    readsome utilise in_avail() pour borner le nombre de caractères lu. Ce qui peut ne pas être ce qui est désiré.

    - il y a un très bon bouquin de Kreft et Langer sur les flux
    - 9, c'est pas tip-top efficace pour une lecture bufferisée
    - il y a une autre solution qui consiste à taper directement dans les streambuf. Jean Marc en parlait dans un autre fil ces jours-ci. Le fil sur l'unicode peut-être ?
    L'avantage d'utiliser le streambuf, c'est qu'on a le nombre de caractères lus. Mais il est possible qu'on puisse aussi utiliser read() et gcount() pour avoir le résultat voulu. J'ai pris l'habitude du streambuf et de sgetn et chaque fois que je vois gcount() je me dis qu'il faudrait que je vérifie si ça résouds bien le problème ou pas. Mais je n'en prend pas la peine sur le moment.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  12. #12
    Membre habitué Avatar de nicolas66
    Profil pro
    Étudiant
    Inscrit en
    Février 2004
    Messages
    326
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2004
    Messages : 326
    Points : 146
    Points
    146
    Par défaut
    L'avantage d'utiliser le streambuf, c'est qu'on a le nombre de caractères lus. Mais il est possible qu'on puisse aussi utiliser read() et gcount() pour avoir le résultat voulu. J'ai pris l'habitude du streambuf et de sgetn et chaque fois que je vois gcount() je me dis qu'il faudrait que je vérifie si ça résouds bien le problème ou pas. Mais je n'en prend pas la peine sur le moment.
    Tu as un exemple sous la main d'un programme de lecture de fichiers utilisant les streambuf ?
    Athlon 6000+ Dual Core & GeForce 8600 GT -- Ubuntu Gutsy

  13. #13
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Tu utilises is->rbuf()->sgetn à peu prêt comme tu utiliserais is->read à part que le résultat est le nombre de caractères lus. Il faut faire attention simplement à la gestion de la fin de fichier et des erreurs car les flags sur is ne sont pas placés.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

Discussions similaires

  1. lecture dans un fichier par bloc
    Par danathane dans le forum Langage
    Réponses: 1
    Dernier message: 15/12/2008, 11h02
  2. lecture ecriture de fichier par blocs
    Par pfeuh dans le forum C
    Réponses: 10
    Dernier message: 06/11/2008, 10h48
  3. Lecture de fichier par onglets spécifiques
    Par david71 dans le forum Macros et VBA Excel
    Réponses: 7
    Dernier message: 19/09/2008, 17h06
  4. [VB6 Débutant] Lecture de fichier par FTP
    Par Tostaki dans le forum VB 6 et antérieur
    Réponses: 8
    Dernier message: 19/06/2008, 23h07
  5. Lire un fichier par bloc de n*m bytes
    Par chaka_zulu dans le forum Langage
    Réponses: 1
    Dernier message: 24/05/2007, 07h26

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