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 :

recuperer le mode d'ouverture d'un fstream


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Juillet 2008
    Messages : 25
    Par défaut recuperer le mode d'ouverture d'un fstream
    bonjour, j'espère que quelqu'un pourra me répondre. Dans un programme, j'utilise des fstream. ma question est la suivante, y a t-il un moyen de récuppérer le bitmask openmode qui est initialisé en partie avec la méthode open(...).

    Je souhaiterais qu'une routine prenne un fstream en parametre et détermine son mode d'ouverture.

    ex:

    void routine (fstream iFstream)
    {
    if(iFstream... ^ ios_base::in) cout<<"flux en lecture"<<endl;
    else cout<<"flux en ecriture"<<endl;
    }

    C'est ce qu'il faut mettre dans le test qui me pose problème
    (L'exemple est bete mais c'est pour illustrer ma demande)

    merci d'avance

  2. #2
    Membre averti
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Avril 2007
    Messages
    47
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Chef de projet MOA
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 47
    Par défaut
    Bonjour,

    je pense que la méthode flags (http://www.cppreference.com/cppio/flags.html) est la réponse à ton problème

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Juillet 2008
    Messages : 25
    Par défaut
    je suis déjà allé voir du coté de cette méthode qui me parrait un peu obscure mais je crois quelle ne concerne que le bitmask fmtflag et pas le bitmask openmode .
    Sauf erreur de ma part bien sur... Merci quand même pour ta réponse rapide

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    Typiquement, je ne vois aucune raison de vouloir savoir comment a été ouvert un flux de fichier...

    Du moins, j'estime (et je ne suis surement pas le seul dans le cas) que, si tu en viens à te poser la question, c'est qu'il y a visibilement un problème de conception quelque part.

    En effet, la décision d'ouvrir un fichier en lecture ou en écriture intervient bien avant celle d'avoir un acces "particulier".

    En outre, la surcharge des opérateurs << et >> aidant, il est normal et cohérent que l'opérateur << soit utilisé pour écrire dans un fichier et que l'opérateur >> serve à lire dedans, et que la variable servant de flux devra donc être du type correspondant

    Au final, tu peux donc te trouver soit dans une situation dans laquelle tu écris deux fonctions (ou méthodes) sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    void readFromFile(const std::string& filename)
    {
        std::ifstream ifs(filename.c_str());
        /* lecture du fichier */
    }
    void writeToFile(const std::string& filename) const
    {
        std::ofstream ofs(filename.c_str());
        /* écriture dans le fichier */
    }
    et dans laquelle tu décidera s'il s'agit de lire ou... d'écrire, soit dans une situation dans laquelle tu surchargera les opérateurs << et >> sous une forme 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
    class MaClass
    {
        /* constructeurs, destructeurs et opérateurs d'affectations sont passés
         * car sans intérêt ici 
         */
        friend std::ostream& operator<<(std::ostream& oss, const MaClass& c)
        {
            /* écriture des informations de la classe dans le flux sortant */
            return oss; //permettra l'appel "en cascade" ;)
        }
        friend std::istream& operator>>(std::istream& iss, MaClass& c)
        {
            /* lecture des informations de la classe au départ du flux entrant */
            return iss;//permettra l'appel "en cascade" ;)
        }
    }
    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

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Juillet 2008
    Messages : 25
    Par défaut
    Merci pour cette réponse pleine de bon sens. La raison pour laquelle je souhaitais connaitre le mode d'ouverture du flux est que je souhaite produire un module d'accès aux données générique. A force d'obstraction, le mode d'ouverture du fichier ne se propage pas dans les classe utilisatrice.
    Or il m'est neccessaire a un moment donné de récupurer un flux et de faire un initR() dans le cas où il est en lecture, et un initW() si il est en ecriture.
    Dans le cas d'un fichier, initR() ne fait rien par contre initW() ecrit l'entete. Cette entet ne peux pas etre ecrite au préalable puisque l'objet qui qui instancie le flux ne connait pas encore les information qui figureront dans l'entete.
    Peut etre est ce un problème se conception bien que je vois difficilement une maniere différente de proceder dans cas ( je reste un débutant et n'est peut etre pas encore assez de clairevoyance quant a la conception d'un module "générique", disons plutot d'abstraction des données)

    Toujours est-il que j'ai opté pour un enum appartenant à la classe contenant le flux qui me dit si le flux est fermé, en lecture, en ecriture ou les deux.
    Je vous remercie pour votre aide, à une prochaine fois!

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Je te déconseillerais de travailler avec un iofstream...

    je te conseillerais de travailler avec deux classe qui instancient le flux:

    la première qui ouvre le fichier "en lecture", et la seconde qui l'ouvre en "écriture".

    Pour toutes les autres classes, les opérateurs << et >> ou les méthodes readFromFile et writeToFile suffisent

    Au final, tu obtiens donc une classe 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
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    /* la classe qui écrit dans le fichier 
     * on fournit le nom de fichier au constructeur qui:
     * - va ouvrir le fichier en écriture
     * - va s'assurer que le fichier est bien ouvert (lancer une exception si ce
     *    n'est pas le cas)
     */
    class Saver
    {
        public:
            Saver(const std::string& filename):
                 ofs(filename.str()), obj(obj)
             {
                 if(!ofs)
                     throw FileNotFound();
            }
            ~Saver(){}
            /* méthode d'écriture de l'objet principal
             * @ in : référence constante vers l'objet qui contient tous les
                      autres
             */
            void Save(const ObjetPrincipal& obj)
            {
                ofs<<obj.entete()
                    <<obj.membre1()
                    <<obj.membre2()
                    <<obj.membre3()
                    <<...
            }
        private:
            std::ofstream ofs;
    };
     
    /* la classe qui lit dans le fichier 
     * on fournit le nom de fichier au constructeur qui:
     * - va ouvrir le fichier en lecture
     * - va s'assurer que le fichier est bien ouvert (lancer une exception si ce
     *    n'est pas le cas)
     */
    class Loader
    {
        public:
            Loader(const std::string& filename):
                 ifs(filename.str())
            {
                if(!ofs)
                    throw FileNotOpen();
            }
            ~Loader(){}
            /* méthode de lecture de l'objet principal
             * @ in : référence (non constante ;) ) vers l'objet qui contient tous
                      les autres
             */
            void load(ObjetPrincipal& obj)
            {
                ifs>>obj.entete()
                    >>obj.membre1()
                    >>obj.membre2()
                    >>obj.membre3()
                    >>...
            }
        private:
            std::ifstream ofs;
    };
    En effet, quand tu prend la décision d'écrire les information, tu va créer une instance de Saver, et appeler la méthode save(), et quand, inversement, tu va vouloir lire les informations, tu va créer une instance de Loader et appeler la méthode load...

    Alternativement, tu peux envisager de créer l'objet qui contient tous les autres sous une forme 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
    class ObjetPrincipal
    {
        public:
            ObjetPrincipal(/* parametres éventuels */): /*liste d'initialisation */
            { /* vérifications éventuelles */
            }
            ~ObjetPrincipal(){/* ce qui va bien */}
            void writeToFile(const std::string& filename)
            {
                /* ouverture du fichier */
                std::ofstream ofs(filename.c_str());
                membre1.writeToStream(ofs);
                membre2.writeToStream(ofs);
                membre3.writeToStream(ofs);
                /*...*/
            }
            void readFromFile(const std::string &filename)
            {
                /* ouverture du fichier */
                std::ifstream ifs(filename.c_str());
                membre1 = Type1::readFromStream(ifs);
                membre2 = Type2::readFromStream(ifs);
                membre3 = Type3::readFromStream(ifs);
            }
    };
    En ayant, pour chaque type quelque chose ressemblant à
    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
    class Type1
    {
        public:
            Type1(/*parametres */):/*liste d'initialisation */
            {/* vérifications */}
            ~Type1(){/* ce qui va bien */}
            void writeToStream(std::ostream& ofs)
            {
                 /*écriture des informations */
            }
            static Type1& readFromStream(std::istream& ifs)
            {
                /* - lecture des informations utiles
                 * - vérification de la cohérence
                 */
                return Type1(/*parametres sur base de la lecture */);
            }
    }
    Le tout en sachant que rien ne t'empêche malgré tout de prévoir un constructeur par défaut pour tes différents objet, et d'invoquer readFromStream pour les différents membres, selon une logique à déterminer, ni d'invoquer writeToStream pour les membres des objets "Type1" et autres

    Quoi qu'il en soit, tu en arrive à une situation qui fait que, quelle que soi ta décision, la sauvegarde ou la lecture se fera "en cascade", et qui t'évite d'avoir à te poser la question de savoir ce que l'utilisateur veut faire
    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

  7. #7
    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 : 50
    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
    Par défaut
    D'autres possibilités :
    - Il est possible de stocker l'information de ton choix directement dans un flux (xalloc, pword, iword)
    - Il est peut-être possible d'utiliser dynamic_cast pour savoir si ton flux est un descendant de ostream
    - Il est peut-être possible de templatiser tout ton code en fonction du type de flux, et d'utiliser la surcharge de fonction pour résoudre ce qui va bien dans les couches basses (c'est ce que fait boost::serialization)
    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.

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

Discussions similaires

  1. Spécifier le mode d'ouverture d'un dossier
    Par wise_mind dans le forum VB 6 et antérieur
    Réponses: 1
    Dernier message: 18/08/2008, 10h34
  2. Modes d'ouvertures des fichiers
    Par Invité dans le forum Bibliothèque standard
    Réponses: 6
    Dernier message: 02/08/2008, 11h17
  3. Mode d'ouverture d'un formulaire
    Par seljack dans le forum Access
    Réponses: 1
    Dernier message: 06/11/2007, 13h24
  4. Modes d'ouvertures Bases par ADO
    Par philnext dans le forum Bases de données
    Réponses: 0
    Dernier message: 18/09/2007, 11h08
  5. mode d'ouverture fichier
    Par jmclej dans le forum Entrée/Sortie
    Réponses: 9
    Dernier message: 12/12/2005, 21h58

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