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 :

Extraire le tableau de bytes d'un std::ostream


Sujet :

Langage C++

  1. #1
    Invité
    Invité(e)
    Par défaut Extraire le tableau de bytes d'un std::ostream
    Salut,

    je voudrais implémenter un système de sérialisation mais sans devoir dépendre de boost, alors, j'ai pensé faire ceci qui me semble être très simple comme solution :

    -Redéfinir les opérateur >> et << et mettre tout ce que je veux sérialiser dans un objet de type ofstream, exactement comme si je voudrais afficher la valeur de mes variables membres sur la console à part que ici je veux les sauvegarder dans un fichier binaire.

    Malheureusement je ne trouve aucune fonction pour récupérer les bytes d'un objet de type ostream...

    Alors donc bon voila je voudrais savoir comment est ce que je peux extraire les bytes des flux standart du c++. (ostream et istream)

    J'ai vu que il y a une classe de base (streambuf) mais je vois aucune fonction pour récupérer le tableau de bytes du buffer. :/

  2. #2
    Invité
    Invité(e)
    Par défaut
    Bon je pense que je vais reprendre les header et les fichiers sources de boost, les mettre dans le répertoire de mon framework et compiler tout ça avec cmake, se sera le plus simple.

  3. #3
    Membre chevronné
    Inscrit en
    Décembre 2010
    Messages
    290
    Détails du profil
    Informations forums :
    Inscription : Décembre 2010
    Messages : 290
    Par défaut
    J'ai vu que il y a une classe de base (streambuf) mais je vois aucune fonction pour récupérer le tableau de bytes du buffer. :/
    Alors soit j'ai pas tout compris à ce que tu essayes de faire, soit il y a une petite confusion à l'origine de tes questions.

    L'idée d'utiliser les opérateurs << et >> pour sérializer des objets est très bonne, et c'est même une convention très utilisée.
    Mais en général, on implémente pas ces opérateurs spécifiquement pour un objet std::ifstream ou un std::ofstream. Plutôt, on les implémentera pour un std::istream (n'importe quel stream d'entrée) ou std::ostream (n'importe quel stream de sortie).
    Du coup, il ne t'est pas nécessaire de "lire les bytes écrits dans std::cout" mais plutôt "écrire directement vers le flux de sortie qui m'intéresse". Je sais pas si je suis très clair.

    Il y a quelque temps, j'avais écrit le code suivant pour une question similaire sur ce forum. Personne ne m'a corrigé donc j'espère qu'il est juste :

    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
     
    /*
        test.cpp
    */
     
    #include <iostream>
    #include <fstream>
    #include <string>
     
    // type de l'objet à sérializer
    class objectToutbete
    {
    public:
         std::string    id;
         std::string    contenu;
    };
     
    // L'opérateur de sortie
    std::ostream&    operator<< (std::ostream& out, const objectToutbete& otb)
    {
        out << otb.id;
        out << " ";
        out << otb.contenu;
        return out;
    }
     
    // L'opérateur d'entrée
    std::istream&    operator>> (std::istream& in, objectToutbete& otb)
    {
        in >> otb.id;
        in >> otb.contenu;
        return in;
    }
     
    int main (int argc, char **argv)
    {
            // un objet à écrire
        objectToutbete    aecrire;
        aecrire.id = "Identifiant";
        aecrire.contenu = "Phi";
     
            // écriture de l'objet vers un fichier
        std::ofstream out ("test.txt");
        out << aecrire << "\n";
        out.close ();
     
            // lecture de l'objet depuis le fichier
        objectToutbete alire;
        std::ifstream    in ("test.txt");
        in >> alire;
     
            // affichage de l'objet lu
        std::cout << "Objet lu : ";
        std::cout << alire;
     
        return 0;
    }

  4. #4
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Ce code me semble raisonnable.

    Je rajoute juste que comme les opérateurs << et >> sont chainables, tu aurais pu les écrire en une ligne.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    // L'opérateur de sortie
    std::ostream&    operator<< (std::ostream& stream, ObjectToutbete const& that) {
        return stream<< that.id << " " << that.contenu;
    }

  5. #5
    Invité
    Invité(e)
    Par défaut Autre problème. (avec boost::serialisation)
    Ok, je vois, donc au lieu de le mettre dans un cout je dois juste le mettre dans un ofstream.(Je savais pas qu'on pouvait faire ça je pensais que les objets de type ostream étaient réservé à la console uniquement)

    Mais il y a un autre problème, en fait, j'utilise des objets polymorphique (c'est à dire des pointeurs vers des objets de classes dérivée) car j'utilise le pattern entité.

    Comment savoir lors de la lecture et de l'écriture le type réel de l'objet (en gros quel opérateur <<) je dois appeler.

    J'ai vu que boost possède un mécanisme permettant de gérer ça à l'aide de la macro BOOST_EXPORT_CLASS_GUID, de plus boost gère toutes les collections de la STL ce qui m'arrange bien vu que je ne dois plus sauvegarder tout ça moi même à l'aide d'une boucle pour les vecteurs.

    Par contre ça ne semble pas fonctionner très bien pour les vecteurs de pointeurs, voici un code ou je veux sauvegarder un vecteur de pointeurs :

    Code cpp : 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
     
    #ifndef T_GROUND
    #define T_GROUND
    #include "../../../../include/odfaeg/Graphics/2D/tile.h"
     
    namespace odfaeg {
        namespace g2d {
    class BigTile : public Entity, public Selectable {
        friend class boost::serialization::access;
    public :
        BigTile() : Entity (Vec3f(0, 0, 0), Vec3f (0, 0, 0), Vec3f (0, 0, 0), "E_BIGTILE") {}
        BigTile  (Vec3f pos);
        bool operator== (Entity &entity);
        void addTile (Tile *tile);
        void removeTile (Tile *tile);
        std::vector<Tile*> getTiles ();
        template <typename Archive>
        void serialize(Archive &ar, const unsigned int version) {
             ar & boost::serialization::base_object<Entity>(*this);
             ar & tiles;
        }
        bool isAnimated() const {
            return false;
        }
        bool isModel() const {
            return false;
        }
        bool selectable() const {
            return true;
        }
        bool isLight() const {
            return false;
        }
        bool isShadow() const {
            return false;
        }
        bool isLeaf() const {
            return false;
        }
    private :
        void recomputeSize();
        std::vector<Tile*> tiles;
    };
    }
    }
    #endif // T_GROUND

    Ca se sérialise bien pour la classe tile toute seule :
    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    void serialize(Archive & ar, const unsigned int version) {
                ar & boost::serialization::base_object<Entity>(*this);
            }

    mais une fois que j'ai des objets qui contiennent des vecteurs de pointeurs vers des autres entités, là, ça ne marche plus, En fait ici, j'ai bien la taille du vecteur de tiles qui vaut un lorsque je rajoute une tile à ma grande tile.

    Le problème c'est que lors de la désérialisation, boost appelle le constructeur par défaut, du coup, la tile de ma grande tile ne conserve pas sa position, sa taille, etc...

    A la compilation j'ai même du déclarer ce constructeur sinon ça ne marchait pas :

    Code cpp : 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
     
    Tile::Tile() : Entity (Vec3f(0, 0, 0), Vec3f(1, 1, 1),Vec3f(0.5f, 0.5f, 0.5f),"E_TILE"){
        Face* face = new Face(sf::TrianglesFan, getTransform());
        Vec3f size(1, 1, 0);
        Vec3f position(0, 0, 0);
        Vec3f origin (0.5f, 0.5f, 0);
        Vertex v1(sf::Vector3f(position.x, position.y, position.z));
        Vertex v2(sf::Vector3f(position.x + size.x, position.y, position.z));
        Vertex v3(sf::Vector3f(position.x + size.x, position.y + size.y, position.z));
        Vertex v4(sf::Vector3f(position.x, position.y + size.y,position.z));
        face->append(v1, 0);
        face->append(v2, 1);
        face->append(v3, 2);
        face->append(v4, 3);
        addFace(face);
    }

    Voici le main :

    Code cpp : 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
     
    #include "odfaeg/Graphics/2D/tGround.h"
    #include "odfaeg/Core/boost/serialization/export.hpp"
    #include "boost/archive/text_oarchive.hpp"
    #include "boost/archive/text_iarchive.hpp"
    BOOST_CLASS_EXPORT_GUID(odfaeg::g2d::Tile, "Tile")
    BOOST_CLASS_EXPORT_GUID(odfaeg::g2d::BigTile, "BigTile")
    int main(int argc, char* args[])
    {
        odfaeg::g2d::Tile tile(nullptr, odfaeg::Vec3f(0, 0, 0), odfaeg::Vec3f(120, 60, 0),sf::IntRect(0, 0, 100, 50));
        odfaeg::g2d::BigTile bt(odfaeg::Vec3f(0, 0, 0));
        bt.addTile(&tile);
        std::ostringstream oss;
        {
            boost::archive::text_oarchive oa(oss);
            oa<<bt;
        }
        std::istringstream iss(oss.str());
        {
            boost::archive::text_iarchive ia(iss);
            ia>>bt;
        }
        odfaeg::g2d::Tile* t = bt.getTiles()[0];
        std::cout<<"tile : "<<t->getPosition()<<t->getSize();
        MyAppli app(sf::VideoMode(800, 600, 32), "Test odfaeg");
     
        return app.exec();
    }

    Donc pas de soucis pour sérialiser les objets sauf pour les vecteurs de pointeurs.

  6. #6
    Membre chevronné
    Inscrit en
    Décembre 2010
    Messages
    290
    Détails du profil
    Informations forums :
    Inscription : Décembre 2010
    Messages : 290
    Par défaut
    Là vraiment c'est un sujet que je ne connais pas du tout.
    Je pense qu'il faudrait déplacer ton dernier message vers une nouvelle question sur le forum, parce que c'est, à mon sens, un sujet différent.

  7. #7
    Invité
    Invité(e)
    Par défaut
    Ok bah je vais déplacer ça dans librairie.

Discussions similaires

  1. [Socket][File] Envoyer un tableau de byte
    Par itsmii dans le forum Entrée/Sortie
    Réponses: 14
    Dernier message: 30/01/2014, 09h10
  2. [VB.NET] Extraire infos d'un tableau de byte()
    Par guillaume1998 dans le forum VB.NET
    Réponses: 4
    Dernier message: 09/11/2005, 08h28
  3. probleme d allocation avec un tableau de BYTE
    Par e1lauren dans le forum C++
    Réponses: 5
    Dernier message: 06/05/2005, 13h42
  4. [VB.NET] Tableau de bytes Lecture/Ecriture
    Par BenoitM dans le forum Windows Forms
    Réponses: 3
    Dernier message: 05/04/2005, 09h51
  5. [C#] Convertir un tableau de byte en Image
    Par goulhasch dans le forum ASP.NET
    Réponses: 4
    Dernier message: 24/01/2005, 10h12

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