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

SL & STL C++ Discussion :

pubsetbuf, comment ça marche?


Sujet :

SL & STL C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Juin 2006
    Messages
    122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Juin 2006
    Messages : 122
    Par défaut pubsetbuf, comment ça marche?
    Hoy, \o

    Petit problème de buffer et de fstream.

    J'ai besoin d'écrire une fonction qui renvois un std::ifstream. Je veux générer mon ifstream à partir d'un bloc de donnée en mémoire. Pour identifier ce bloc, j'ai donc un char* pour le début de mes données et un long pour la taille.

    J'ai cherché des exemples sur le net, j'ai trouvé un petit bout de code et je l'ai convertit à mon avantage :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    std::ifstream Game::GetBinaries(std::string &name)
    {
    	std::ifstream file;
    	file.rdbuf()->pubsetbuf(game_binaries.GetFile(name), game_binaries.GetFileSize(name));
    	return file;
    }
    game_binarie.GetFile() renvois un char *, GetFileSize() renvois un long.

    De ce que j'ai lut, le pubsetbuf est une méthode public de basic_streambuf pour assigner un buffer perso à notre objet ifstream, hors, j'obiens une jolie erreur :
    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
     
    1>d:\Microsoft Visual Studio 9.0\VC\include\fstream(676) : error C2248: 'std::basic_ios<_Elem,_Traits>::basic_ios' : cannot access private member declared in class 'std::basic_ios<_Elem,_Traits>'
    1>        with
    1>        [
    1>            _Elem=char,
    1>            _Traits=std::char_traits<char>
    1>        ]
    1>        d:\Microsoft Visual Studio 9.0\VC\include\ios(151) : see declaration of 'std::basic_ios<_Elem,_Traits>::basic_ios'
    1>        with
    1>        [
    1>            _Elem=char,
    1>            _Traits=std::char_traits<char>
    1>        ]
    1>        This diagnostic occurred in the compiler generated function 'std::basic_ifstream<_Elem,_Traits>::basic_ifstream(const std::basic_ifstream<_Elem,_Traits> &)'
    1>        with
    1>        [
    1>            _Elem=char,
    1>            _Traits=std::char_traits<char>
    1>        ]
    What is wrong? rdbuf() permet bien d'acceder au buf, vu qu'il renvoit un pointeur, et j'utilise pubsetbuf pour changer le buffer de mon stream. :\

  2. #2
    screetch
    Invité(e)
    Par défaut
    ifstream n'est pas copiable.

  3. #3
    Membre confirmé
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Juin 2006
    Messages
    122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Juin 2006
    Messages : 122
    Par défaut
    Ha... Ha bah ouais.

    Bon jvais prendre ma fonction l'autre sens alors. :\

    Merci

  4. #4
    Membre confirmé
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Juin 2006
    Messages
    122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Juin 2006
    Messages : 122
    Par défaut
    Bon nouveau problème toujours avec les ifstream (ou les stream tout court, je sais pas trop =p).

    Je dispose de fichiers binaires. Ces fichiers ont été généré grâce à boost::serialization, ce sont des boost::archive::binary_oarchive sauvegardée sur le disque.

    Pour l'instant je n'ai que 2 de ces fichiers, mais arrivera un moment dans le développement de mon programme où j'en aurai peut-être plusieurs 100ènes. J'ai donc rassemblé les fichiers en un seul gros fichier binaire.

    Depuis ce gros fichier binaire (qu'on appellera fichier .dat), j'accède à chaque élément via une pair de fonction : GetFile() qui renvoi un pointeur vers le début des données qui m'intéresse, et GetFileSize() qui renvoi la taille des données.

    Le but ici, c'est de récupérer ces donnée qui correspondent à mes fichiers binaire boost, les convertir en un istream valide afin de les utiliser dans une iarchive.

    Si je n'utilise pas le .dat, donc que j'ai mes fichiers binaire boost dans le repertoire de base de mon programme, je les charge de la manière suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    std::string filename = "filename";
    std::ifstream file(filename.c_str());
    boost::archive::binary_iarchive ar(file);
    Ca, je l'ai testé, ça marche, c'est la façon la plus simple de charger les fichiers, qu'on peut voir dans le tutoriel sur boost::serialization.

    Maintenant j'essaye de charger ça depuis mon fichier .dat, ce qui donne ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    // On extrait les données du .dat, ici, tout va bien
    std::string filename = "filename"; // Le nom du fichier que je veux extraire
    cDAT data.Read("monFichierDat.dat"); // Ouvre le fichier .dat en mode binaire
    char *buff = data.GetFile(filename); // On récupère le début des données
    long size = data.GetFileSize(filename); // On récupère la taille
     
    // On créé un ifstream et on lui injecte les données extraite du .dat
    std::ifstream file; // On créé notre ifstream
    f.rdbuf()->pubsetbuf(buff, size); // On injecte les données
    boost::archive::binary_iarchive ar(file); // On donne le ifstream pour charger notre archive.
    Là, je test et ça ne marche pas. Le debugger me génère un breakpoint lors de la création de l'archive, ce qui me laisse penser que j'ai mal préparé mon ifstream. Et comme je ne suis pas encore à l'aise avec les stream, je vous pose la question : qu'est ce qui manque à mon stream pour qu'il soit valide?

    Le binary_iarchive peut prendre en paramètre un std::istream & ou un std::streambuf &, je ne sais pas si le ifstream est réellement utile dans ce cas, mais je ne vois pas trop quoi utiliser d'autre. :\

    Vala, la moindre idée me serai d'une grande aide. =p

  5. #5
    Membre confirmé
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Juin 2006
    Messages
    122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Juin 2006
    Messages : 122
    Par défaut
    Haha, haha, haha...

    Le fait de poster ça aide à réfléchir faut croire.

    Une classe toute bête qui permet de convertir un pointeur sur des donnée + la longueur des donnée, c'est le string... Je créé un stringstream pour pouvoir le passer en paramètre de mon archive comme un istream, et ça marche.

    Ca donne donc ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    // On extrait les données du .dat, ici, tout va bien
    std::string filename = "filename"; // Le nom du fichier que je veux extraire
    cDAT data.Read("monFichierDat.dat"); // Ouvre le fichier .dat en mode binaire
    char *buff = data.GetFile(filename); // On récupère le début des données
    long size = data.GetFileSize(filename); // On récupère la taille
     
    // On créé un stringstream et lui injecte un string à partir des données extraites
    std::stringstream ss;
    ss << std::string(buff, size);
    boost::archive::binary_iarchive archive(ss);
    Ou comment résoudre un problème soit même.

  6. #6
    Membre éclairé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Par défaut
    Et voici de quoi éviter un copie inutile.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    // On créé un stringstream et lui injecte un string à partir des données extraites
    std::stringstream ss;
    ss.write(buff, size);
    boost::archive::binary_iarchive archive(ss);
    Je ne supporte pas les stream, c'est le truc le plus obscur en C++, et en plus c'est pas performant.

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

Discussions similaires

  1. ToAsciiEx, comment cela marche ?
    Par mikyfpc dans le forum C++Builder
    Réponses: 2
    Dernier message: 17/02/2004, 21h39
  2. [MFC] list box : comment ça marche
    Par runn2 dans le forum MFC
    Réponses: 4
    Dernier message: 28/01/2004, 12h36
  3. [SYNEDIT] -> Comment ça marche ?
    Par MaTHieU_ dans le forum C++Builder
    Réponses: 2
    Dernier message: 18/01/2004, 19h11
  4. [TP][Turbo Vision] comment ça marche ??
    Par Costello dans le forum Turbo Pascal
    Réponses: 7
    Dernier message: 05/08/2003, 00h24
  5. [update][req. imbriquee] Comment ca marche ??
    Par terziann dans le forum Langage SQL
    Réponses: 3
    Dernier message: 11/07/2003, 12h51

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