webentwicklung-frage-antwort-db.com.de

Kopieren Sie den Inhalt einer Streambuf in eine Zeichenfolge

Anscheinend mag boost::asio::async_read keine Strings, da die einzige Überladung von boost::asio::buffer mir erlaubt, const_buffers zu erstellen, also bleibe ich beim Lesen alles in einer Streambuf.
Nun möchte ich den Inhalt der Streambuf in einen String kopieren, aber er unterstützt anscheinend nur das Schreiben in char * (sgetn()), das Erstellen eines istreams mit der Streambuf und die Verwendung von getline()

Gibt es eine andere Möglichkeit, eine Zeichenfolge mit dem Inhalt von streambufs ohne übermäßiges Kopieren zu erstellen?

30
tstenner

Ich weiß nicht, ob es als " übermäßiges Kopieren " zählt, aber Sie können einen Stringstream verwenden:

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

Um alles aus stdin in einen String zu lesen, tun Sie

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

Alternativ können Sie auch einen istreambuf_iterator verwenden. Sie müssen messen, ob dieser oder der obige Weg schneller ist - ich weiß es nicht.

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

Beachten Sie, dass someStreamBuf oben für einen streambuf* stehen soll. Nehmen Sie daher die Adresse entsprechend vor. Beachten Sie auch die zusätzlichen Klammern um das erste Argument im letzten Beispiel, damit es nicht als Funktionsdeklaration interpretiert wird, die einen String zurückgibt und einen Iterator und einen anderen Funktionszeiger ("ärgerlichste Analyse") verwendet.

Es ist wirklich begraben in den Dokumenten ...

Gegebener 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);
37
Sean DeNigris

Eine andere Möglichkeit mit boost::asio::streambuf ist die Verwendung von boost::asio::buffer_cast<const char*>() in Verbindung mit boost::asio::streambuf::data() und boost::asio::streambuf::consume() wie folgt:

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 funktioniert nicht mit normalen Streambufs und wird möglicherweise als schmutzig betrachtet, scheint jedoch der schnellste Weg zu sein.

24
tstenner

Für boost::asio::streambuf finden Sie möglicherweise eine Lösung wie diese: 

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

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

Drucken Sie die Zeichenfolge aus:

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

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

13
iericzhou

Man kann die Zeichen auch von asio::streambuf mit std::basic_streambuf::sgetn beziehen:

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

Der Grund, aus dem Sie nur const_buffer aus std :: string erstellen können, ist, dass std :: string das direkte Zeiger-basierte Schreiben in seinem Vertrag explizit nicht unterstützt. Sie könnten etwas Böses tun, z. B. die Größe Ihres Strings auf eine bestimmte Größe ändern, dann const_cast die Konstante von c_str () eingeben und wie einen rohen Zeichenpuffer behandeln, aber das ist sehr ungezogen und wird Sie eines Tages in Schwierigkeiten bringen.

Ich verwende std :: vector für meine Puffer, denn solange der Vektor die Größe nicht ändert (oder Sie vorsichtig mit der Größenänderung umgehen), können Sie direkt mit dem Zeiger schreiben. Wenn ich etwas von den Daten als std :: string brauche, muss ich es herauskopieren, aber so wie ich mit meinen Lesepuffern umgehe, muss alles, was über den Read-Callback hinausgehen muss, unbedingt kopiert werden.

0
user121826

Eine einfachere Antwort wäre, es in std::string zu konvertieren und es irgendwie zu manipulieren

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

Geben Sie einen sehr prägnanten Code für die Aufgabe.

0
DevMac