2010-08-31 7 views
0

J'ai besoin d'obtenir tout le contenu d'un flux, sans vraiment les extraire (tout comme stringstream::str()). J'ai essayé basic_stringbuf::str(), mais il se comporte incorrectement lorsque le flux est vide. Pour éviter ce cas, j'ai essayé le basic_stringbuf::in_avail(), mais cela n'a pas très bien marché non plus.Quelle est la fiabilité de basic_stringbuf :: in_avail() et basic_stringbuf :: str()?

Dans le cas de test suivant, in_avail() ne retourne pas le nombre d'éléments disponibles sur le flux, et str() retours plus éléments que ce qui est actuellement là-bas:

#include <iostream> 
#include <iterator> 
#include <vector> 
#include <sstream> 

// extracts everything from the stream 
std::vector<unsigned char> stream2vector(std::basic_istream<unsigned char>& stream) 
{ 
    std::vector<unsigned char> retreivedData; 
    std::istreambuf_iterator<unsigned char> it(stream); 
    const std::istreambuf_iterator<unsigned char> endOfStream; 
    retreivedData.insert(retreivedData.begin(), it, endOfStream); 
    return retreivedData; 
} 

int main() { 
    std::basic_stringbuf<unsigned char> buf; 
    std::basic_iostream<unsigned char> stream(&buf); 
    unsigned char array[5] = { 1, 2, 3, 4, 5 }; 
    stream.write(array, 5); 


    std::cout << "rdbuf()->in_avail(): " << buf.in_avail() << "\n"; 
    std::vector<unsigned char> d1 = stream2vector(stream); 
    std::cout << "d1.size(): " << d1.size() << "\n"; 

    std::cout << "\n"; 
    // d2 should be empty 
    std::vector<unsigned char> d2 = stream2vector(stream); 
    std::cout << "d2.size(): " << d2.size() << "\n"; 
    std::basic_string<unsigned char> s = buf.str(); 
    std::cout << "buf.str().size(): " << buf.str().size() << "\n"; 
} 

Compiler sur g ++ 4.4, le la sortie est:

rdbuf()->in_avail(): 1 // expected: 5 
d1.size(): 5 // as expected 

d2.size(): 0 // as expected 
buf.str().size(): 5 // expected: 0 

Qu'est-ce que je fais mal? Quelle est la meilleure façon de faire ce que j'essaye?

Merci beaucoup.

Répondre

0

in_avail est le nombre de caractères prêts à être lus à partir du tampon, pas la taille du tampon lui-même. Il est vraiment permis de retourner toute valeur non nulle ici.

Cependant, je ne peux pas répondre quelle est la meilleure façon de ce que vous faites, parce que je ne sais pas ce que vous faites. Si vous avez déjà des choses comme un tableau unsigned char, alors vous allez vouloir faire:

std::vector<unsigned char> data(array, array + sizeof(array)/sizeof(unsigned char)); 

Si vous essayez juste de lire un flux entier dans un vecteur, alors je ferais exactement ce que vous re faire; Je venais de remplacer vous êtes fonction stream2vector avec cela, équivalent plus simple:

// extracts everything from the stream 
std::vector<unsigned char> stream2vector(std::basic_istream<unsigned char>& stream) 
{ 
    std::istreambuf_iterator<unsigned char> it(stream); 
    const std::istreambuf_iterator<unsigned char> endOfStream; 
    return std::vector<unsigned char>(it, endOfStream); 
} 

Je ne suis pas tout à fait sûr pourquoi vous êtes spécialisé toutes les opérations ici pour unsigned char - Je voudrais simplement utiliser la valeur par défaut char versions, car unsigned char est autorisé à avoir la même taille qu'un short, ce qui n'est probablement pas ce que vous voulez (mais je ne suis au courant d'aucune implémentation qui le fasse).

+0

Merci pour les commentaires. Ce que j'essaie de faire est de lire tout le contenu du flux sans les extraire, ce que fait actuellement 'stream2vector'. De cette façon, je peux appeler 'stream2vector' à plusieurs reprises sur un flux donné (comme le montre l'exemple, cela n'est pas possible avec cette implémentation basée sur l'itérateur). –

+0

Ou, pour le dire autrement, j'essaie d'écrire 'std :: vector stream2vector (const std :: basic_istream & stream)'. –

+0

@Pedro: Ok, alors sauvegardez simplement la position du pointeur get (avec 'tellg'), puis utilisez' seekg' lorsque vous avez fini de repositionner le pointeur get. –

Questions connexes