Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Lecture d'un flux et ecriture dans un ostream

3 réponses
Avatar
Philippe MESMEUR
Je cherche =E0 =E9crire une fonction qui lirait des donn=E9es sur le r=E9se=
au
via la fonction InternetReadFile (dont le prototype est proche de la
fonction write) et =E9crirait les donn=E9es lu dans un osteam.

Si l'ostream est un fichier (c'est =E0 dire si il n'a pas de taille
d=E9finie) alors la fonction =E9crirait dans le dedans jusqu'=E0 ce que
InternetReadFile indique qu'il n'y a plus de donn=E9es =E0 lire

Si l'ostream est de type buffer (cf. mon message d'hier ;-)) la
fonction remplirait le buffer et devrait =EAtre re-appel=E9e pour avoir la
suite des donn=E9es.


Je cherche =E0 =E9crire cette fonction de la mani=E8re la plus propre
possible (pas du bricolage) mais comme je ne m'y connais pas trop sur
les stream std, je m'en remet =E0 vous

Merci d'avance
Philippe

3 réponses

Avatar
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'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.
Avatar
Philippe MESMEUR
On 31 déc, 12:18, Fabien LE LEZ wrote:
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.


Avatar
James Kanze
On Dec 31 2009, 10:57 am, Philippe MESMEUR
wrote:
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