web-dev-qa-db-ja.com

streambufの内容を文字列にコピーします

どうやら_boost::asio::async_read_のオーバーロードは_boost::asio::buffer_ sの作成のみを許可するため、_const_buffer_は文字列が好きではないため、すべてをstreambufに読み込むのに悩まされています。
今、streambufの内容を文字列にコピーしたいのですが、char *(sgetn())への書き込みのみをサポートし、streambufでistreamを作成し、getline()

過度のコピーをせずにstreambufsの内容で文字列を作成する他の方法はありますか?

34
tstenner

過剰コピー」としてカウントされるかどうかはわかりませんが、文字列ストリームを使用できます。

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

同様に、stdinから文字列にすべてを読み取るには、次のようにします。

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

または、istreambuf_iteratorを使用することもできます。あなたはこれまたは上記の方法がより速いかどうかを測定する必要があります-私は知りません。

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

上記のsomeStreamBufstreambuf*を表すことを目的としているため、必要に応じてアドレスを取得してください。また、最後の例の最初の引数を囲む追加の括弧にも注意してください。これは、文字列を返し、イテレータと別の関数ポインタ(「最も厄介な解析」)を取る関数宣言として解釈されないようにするためです。

それは本当に埋もれている ドキュメント内 ...

与えられたboost::asio::streambuf bsize_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);
42
Sean DeNigris

_boost::asio::streambuf_のもう1つの可能性は、boost::asio::buffer_cast<const char*>()およびboost::asio::streambuf::data()と組み合わせてboost::asio::streambuf::consume()を次のように使用することです。

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

これは通常のstreambufでは機能せず、ダーティと見なされる可能性がありますが、それを行うには最速の方法のようです。

24
tstenner

ために boost::asio::streambuf次のような解決策を見つけることができます:

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

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

文字列を出力します。

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

ここにあります: http://www.boost.org/doc/libs/1_49_0/doc/html/boost_asio/reference/async_read_until/overload3.html

13
iericzhou

asio::streambufを使用して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);
1
ArtemGr

Std :: stringからのみconst_bufferを作成できるのは、std :: stringが明示的にそのコントラクトでの直接ポインターベースの書き込みをサポートしていないためです。文字列のサイズを特定のサイズに変更し、c_str()から定数をconst_castし、それをraw char *バッファーのように扱うなど、何か悪いことをすることもできますが、それは非常にいたずらであり、いつかトラブルに巻き込まれるでしょう。

ベクトルのサイズが変更されない限り(またはサイズ変更に注意して対処している限り)、バッファにstd :: vectorを使用します。ダイレクトポインタの書き込みは問題なく行えます。 std :: stringとしてデータの一部が必要な場合は、それをコピーする必要がありますが、読み取りバッファーを処理する方法では、読み取りコールバックを超えて持続する必要があるものはすべて、コピーする必要があります。

0
user121826

より簡単な答えは、それをstd::stringに変換し、次のように操作することです。

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

タスクに非常に簡潔なコードを与える。

0
DevMac