Frage

Offenbar boost::asio::async_read wie Strings nicht, als die einzige Überlast von boost::asio::buffer mir erlaubt const_buffers zu erstellen, so dass ich bin fest mit alles, was zu einem streambuf lesen.
Jetzt möchte ich den Inhalt des streambuf in einen String kopieren, aber es anscheinend unterstützt nur auf char * Schreiben (sgetn()), die Schaffung eines istream mit dem streambuf und mit getline().

Gibt es eine andere Art und Weise eine Zeichenkette mit dem streambufs Inhalt ohne übermäßiges Kopieren?

zu erstellen
War es hilfreich?

Lösung

Ich weiß nicht, ob es gilt als „ übermäßiges Kopieren “, aber Sie können einen string verwenden:

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

Wie, alles von stdin in einen String zu lesen, tut

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

Alternativ können Sie auch eine istreambuf_iterator verwenden. Sie werden, ob schneller diese oder die obige Art und Weise haben zu messen ist -. Ich weiß nicht,

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

Beachten Sie darüber someStreamBuf soll eine streambuf* darstellen, so nehmen seine Adresse als angemessen. Beachten Sie auch die zusätzlichen Klammern um das erste Argument im letzten Beispiel, so dass es nicht interpretieren ist es als Funktionsdeklaration einen String zurückkehrt und einen Iterator und einen anderen Funktionszeiger nehmen ( „drängendsten Parse“).

Andere Tipps

Es ist wirklich begraben in der Dokumentation ...

Bei boost::asio::streambuf b mit 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);

Eine weitere Möglichkeit mit boost::asio::streambuf ist boost::asio::buffer_cast<const char*>() in Verbindung mit boost::asio::streambuf::data() und boost::asio::streambuf::consume() wie folgt zu verwenden:

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);

Dies wird nicht mit normalen streambufs arbeiten und könnte schmutzig angesehen werden, aber es scheint der schnellste Weg, um es zu tun.

Für boost::asio::streambuf Sie können eine Lösung wie diese finden:

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

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

Drucken Sie die Zeichenfolge:

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

Sie können finden Sie hier: http: // www. boost.org/doc/libs/1_49_0/doc/html/boost_asio/reference/async_read_until/overload3.html

Man kann auch die Zeichen aus asio::streambuf mit std::basic_streambuf::sgetn erhalten:

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

Der Grund, warum Sie nur const_buffer von std :: string erstellen können, ist, weil std :: string nicht explizit direktes Pointer-basierte unterstützt Schreiben in seinem Vertrag. Sie könnten etwas Böses tun wie die Zeichenfolge zu einer bestimmten Größe die Größe, dann const_cast der Konstantheit von c_str () und behandeln sie wie ein rohes char * buffer, aber das ist sehr frech und werden Sie in Schwierigkeiten eines Tages erhalten.

Ich benutze std :: vector für meine Puffer, denn solange der Vektor der Größe nicht (oder Sie sind vorsichtig mit Größenänderung zu behandeln), die Sie gerade fein direkte Zeiger Schreiben tun. Wenn ich einige der Daten als std :: string muß, habe ich es kopieren, aber die Art, wie ich mit meinen Lesepuffern beschäftigen, alles, was über den Lese Rückruf dauern muss muss unabhängig abgeschrieben werden.

Eine einfachere Antwort wäre es in std::string zu konvertieren und manipulieren, um sie einige, was wie folgt

 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;
}

einen sehr knappen Code für die Aufgabe geben.

Ich denke, es ist eher wie:


streambuf.commit( number_of_bytes_read );

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

Ich habe nicht in den basic_streambuf Code aussieht, aber ich glaube, das sollte nur eine Kopie in die Zeichenfolge sein.

testete ich die erste Antwort und bekam Fehler einen Compiler bei der Verwendung von „g ++ -std = c ++ 11“ Kompilieren Was für mich gearbeitet wurde:

        #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(); 

Dies kompiliert und ausgeführt wird.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top