Question

Apparemment boost::asio::async_read n'aime pas les chaînes, comme la seule surcharge de boost::asio::buffer me permet de créer const_buffers, donc je suis coincé avec la lecture tout en streambuf.
Maintenant, je veux copier le contenu du streambuf dans une chaîne, mais il supporte apparemment seulement écrit char * (sgetn()), la création d'un istream avec le streambuf et en utilisant getline().

Y at-il une autre façon de créer une chaîne avec le contenu de la copie sans streambufs excessive?

Était-ce utile?

La solution

Je ne sais pas si ce compte comme " copie excessive ", mais vous pouvez utiliser un stringstream:

std::ostringstream ss;
ss << someStreamBuf;
std::string s = ss.str();

Comme, de lire tout de stdin dans une chaîne, faire

std::ostringstream ss;
ss << std::cin.rdbuf();
std::string s = ss.str();

Vous pouvez également utiliser un istreambuf_iterator. Vous devrez mesurer si ce ou la manière ci-dessus est plus rapide -. Je ne sais pas

std::string s((istreambuf_iterator<char>(someStreamBuf)), 
               istreambuf_iterator<char>());

Notez que someStreamBuf ci-dessus est censé représenter un streambuf*, afin de prendre son adresse, le cas échéant. Notez également les parenthèses supplémentaires dans le premier argument dans le dernier exemple, de sorte qu'il ne l'interprète pas comme une déclaration de fonction renvoyant une chaîne et prendre un itérateur et un autre pointeur de fonction ( « parse le plus contrariant »).

Autres conseils

Il est vraiment enterré dans la documentation ...

Compte tenu boost::asio::streambuf b, avec size_t buf_size ...

boost::asio::streambuf::const_buffers_type bufs = b.data();
std::string str(boost::asio::buffers_begin(bufs),
                boost::asio::buffers_begin(bufs) + buf_size);

Une autre possibilité avec boost::asio::streambuf est d'utiliser boost::asio::buffer_cast<const char*>() conjointement avec boost::asio::streambuf::data() et boost::asio::streambuf::consume() comme ceci:

const char* header=boost::asio::buffer_cast<const char*>(readbuffer.data());
//Do stuff with header, maybe construct a std::string with std::string(header,header+length)
readbuffer.consume(length);

Cela ne fonctionne pas avec streambufs normal et peut être considéré comme sale, mais il semble être le moyen le plus rapide de le faire.

Pour boost::asio::streambuf vous pouvez trouver une solution comme ceci:

    boost::asio::streambuf buf;
    /*put data into buf*/

    std::istream is(&buf);
    std::string line;
    std::getline(is, line);

Imprimer la chaîne:

    std::cout << line << std::endl;

Vous trouverez ici: http: // www. boost.org/doc/libs/1_49_0/doc/html/boost_asio/reference/async_read_until/overload3.html

On peut aussi obtenir les caractères de asio::streambuf en utilisant std::basic_streambuf::sgetn:

asio::streambuf in;
// ...
char cbuf[in.size()+1]; int rc = in.sgetn (cbuf, sizeof cbuf); cbuf[rc] = 0;
std::string str (cbuf, rc);

La raison pour laquelle vous ne pouvez créer const_buffer de std :: string est parce que std :: string ne supporte pas explicitement l'écriture à base de pointeur direct dans son contrat. Vous pouvez faire quelque chose comme mal redimensionner votre chaîne à une certaine taille, puis const_cast la constness de c_str () et de la traiter comme un tampon charbon brut *, mais c'est très méchant et vous obtiendrez un jour en difficulté.

J'utilise std :: vecteur pour mes tampons parce que tant que le vecteur ne redimensionne pas (ou si vous êtes prudent de traiter avec le redimensionnement), vous pouvez faire l'écriture pointeur direct très bien. Si j'ai besoin des données en tant que std :: string, je dois le copier, mais la façon dont je traite mes tampons de lecture, tout ce qui doit durer au-delà du rappel de lecture doit être copié sur quel que soit.

A serait de réponse plus simple convertir en std::string et manipuler un peu comme ça que

 std::string buffer_to_string(const boost::asio::streambuf &buffer)
 {
  using boost::asio::buffers_begin;
  auto bufs = buffer.data();
  std::string result(buffers_begin(bufs), buffers_begin(bufs) + buffer.size());
 return result;
}

Donner un code très concis pour la tâche.

Je pense qu'il est plus comme:


streambuf.commit( number_of_bytes_read );

istream istr( &streambuf );
string s;
istr >> s;

Je ne l'ai pas regardé dans le code basic_streambuf, mais je crois que cela devrait être juste une copie dans la chaîne.

Je l'ai testé la première réponse et a obtenu une erreur de compilation lors de la compilation en utilisant « g ++ std = c ++ 11 » Ce qui a fonctionné pour moi était:

        #include <string>
        #include <boost/asio.hpp>
        #include <sstream>           
        //other code ...
        boost::asio::streambuf response;
        //more code
        std::ostringstream sline;
        sline << &response; //need '&' or you a compiler error
        std::string line = sline.str(); 

compilé et a couru.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top