Lecture d'un flux et ecriture dans un ostream

Le
Philippe MESMEUR
Je cherche à écrire une fonction qui lirait des données sur le rése=
au
via la fonction InternetReadFile (dont le prototype est proche de la
fonction write) et écrirait les données lu dans un osteam.

Si l'ostream est un fichier (c'est à dire si il n'a pas de taille
définie) alors la fonction écrirait dans le dedans jusqu'à ce que
InternetReadFile indique qu'il n'y a plus de données à lire

Si l'ostream est de type buffer (cf. mon message d'hier ;-)) la
fonction remplirait le buffer et devrait être re-appelée pour avoir la
suite des données.


Je cherche à écrire cette fonction de la manière la plus propre
possible (pas du bricolage) mais comme je ne m'y connais pas trop sur
les stream std, je m'en remet à vous

Merci d'avance
Philippe
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Fabien LE LEZ
Le #20866001
On Thu, 31 Dec 2009 02:57:14 -0800 (PST), Philippe MESMEUR

et écrirait les données lu dans un osteam.
[...] Si l'ostream est de type buffer [...]



Pourquoi ?

Si tu as un buffer de taille définie, tu peux le passer directement à
InternetReadFile, sans encapsuler tout ça dans du ostream.

Mais si on creuse un peu plus : pourquoi diable veux-tu utiliser un
buffer ? Utilise donc std::string et std::stringstream, et ton
programme n'en sera que plus fiable (et facile à programmer, ce qui va
souvent ensemble).

D'autant que si ton buffer est trop petit, InternetReadFile va se
plaindre, tu vas devoir remonter l'erreur, etc.
Prévois du paracétamol.
Philippe MESMEUR
Le #20865991
On 31 déc, 12:18, Fabien LE LEZ
On Thu, 31 Dec 2009 02:57:14 -0800 (PST), Philippe MESMEUR

>et écrirait les données lu dans un osteam.
>[...] Si l'ostreamest de type buffer [...]

Pourquoi ?

Si tu as un buffer de taille définie, tu peux le passer directement à
InternetReadFile, sans encapsuler tout ça dans duostream.




Ou mais je souhaite que ma fonction puisse lire des données via
InternetReadFile et les écrire dans un ostream, indépendamment que
c'est ostream encapule un fichier, un buffer ou autre chose.

Mais si on creuse un peu plus : pourquoi diable veux-tu utiliser un
buffer ? Utilise donc std::string et std::stringstream, et ton
programme n'en sera que plus fiable (et facile à programmer, ce qui va
souvent ensemble).

D'autant que si ton buffer est trop petit, InternetReadFile va se
plaindre, tu vas devoir remonter l'erreur, etc.
Prévois du paracétamol.


James Kanze
Le #20871121
On Dec 31 2009, 10:57 am, Philippe MESMEUR
Je cherche à écrire une fonction qui lirait des données sur le
réseau via la fonction InternetReadFile (dont le prototype est
proche de la fonction write) et écrirait les données lu dans
un osteam.



Si l'ostream est un fichier (c'est à dire si il n'a pas de
taille définie) alors la fonction écrirait dans le dedans
jusqu'à ce que InternetReadFile indique qu'il n'y a plus de
données à lire



Si l'ostream est de type buffer (cf. mon message d'hier ;-))
la fonction remplirait le buffer et devrait être re-appelée
pour avoir la suite des données.



Ça dépend de ton implémentation du buffer_streambuf (ou comment
tu l'appèles). L'implémentation la plus naturelle, à mon avis,
se servira de std::vector< char > (c'est le type naturel d'un
buffer), et il n'y aura jamais besoin de le reinitialiser. Mais
à la fin, c'est toi que définit le streambuf, et c'est toi qui
établis les règles.

Je cherche à écrire cette fonction de la manière la plus
propre possible (pas du bricolage) mais comme je ne m'y
connais pas trop sur les stream std, je m'en remet à vous



Alors, la première chose, c'est d'apprendre sur les stream
standard. Parce qu'utiliser un outil qu'on ne connaît pas ne
mène jamais à quelque chose de bien. Mais dans ce cas-ci, ce
qu'il te faut savoir n'est pas énorme : tous les put, write, et
de ostream renvoie à la fin au streambuf pour les sorties




physiques des caractères. En se servant uniquement de deux
fonctions : sputc et sputn. Fonctions publiques qui elles se
servent des fonctions virtuelles de xsputn et de overflow. Et il
existe une version par défaut de la première, qui l'implémente
en fonction de la seconde. (En fait, en fonction de sputc, mais
sputc, qui elle n'appelle que overflow.) Alors, l'impémentation
la plus simple serait simplement :

class buffering_streambuf : public std::streambuf
{
std::vector< char > buffer;
protected:
virtual int overflow( int ch )
{
if ( ch != EOF )
buffer.push_back( ch );
return ch == EOF ? '' : ch;
}
public:
// accès au buffer, etc.
};

Pour éviter quelques appels virtuels, il pourrait être
préferrable de rendre la bufferisation visible à sputc et
sputn :

class buffering_streambuf : public std::streambuf
{
std::vector< char > buffer;
protected:
virtual int overflow( int ch )
{
if ( ch != EOF )
buffer.push_back( ch );
size_t current = buffer.size();
buffer.resize( buffer.capacity() );
setp( &buffer[0] + current,
&buffer[0] + buffer.size());
return ch == EOF ? '' : ch;
}
public:
// accès au buffer, etc.
// Les fonctions d'accès doivent prendre en compte
// la position courante, c-à-d pptr. Par exemple:
typedef std::vector< char >::const_iterator iterator;
iterator begin() const
{
return buffer.begin();
}
iterator end() const
{
return buffer.begin() + (pptr() - &buffer[0]);
}
};

--
James Kanze
Publicité
Poster une réponse
Anonyme