streambuf の内容を文字列にコピーします
-
22-08-2019 - |
質問
どうやら boost::asio::async_read
唯一のオーバーロードとして文字列は好きではありません boost::asio::buffer
作成できるようにします const_buffer
そのため、すべてを streambuf に読み込むことにこだわっています。
ここで、streambuf の内容を文字列にコピーしたいのですが、どうやら char* への書き込みのみをサポートしているようです (sgetn()
)、streambuf を使用して istream を作成し、使用します getline()
.
過剰なコピーを行わずに、streambufs の内容を含む文字列を作成する他の方法はありますか?
解決
私はそれが "の過度のコピーの" としてカウントするかどうかわかりませんが、あなたはにstringstreamを使用することができます:
をstd::ostringstream ss;
ss << someStreamBuf;
std::string s = ss.str();
のように、文字列に標準入力からすべてを読むために、行う
std::ostringstream ss;
ss << std::cin.rdbuf();
std::string s = ss.str();
また、あなたはまた、istreambuf_iterator
を使用することができます。あなたはこのまたは上記の方法が高速であるかどうかを測定する必要があります - 私は知りません。
std::string s((istreambuf_iterator<char>(someStreamBuf)),
istreambuf_iterator<char>());
上記someStreamBuf
注streambuf*
を表すので、必要に応じてそのアドレスを取ることを意味します。それは、文字列を返す関数の宣言としてそれを解釈してイテレータと他の関数ポインタ(「最も厄介なパース」)を服用しないように。また、最後の例では、最初の引数の周りに追加の括弧に注意します。
他のヒント
それだの本当にの埋葬<のhref = "http://www.boost.org/doc/libs/1_52_0/doc/html/boost_asio/overview/core/buffers.html" のrel =ドキュメントの "nofollowをさnoreferrer"> の...
boost::asio::streambuf b
... とを考えると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);
別の可能性 boost::asio::streambuf
使うことです 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 では機能せず、汚いと思われるかもしれませんが、これが最も速い方法のようです。
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する
1つはまた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);
あなただけのstd ::文字列からconst_bufferを作成できる理由があります。あなたはその後、c_str(からconst性const_castを、特定のサイズにあなたの文字列のサイズを変更するような何か悪を行う)と、生のchar *バッファのように扱うが、それは非常にいたずらだといつかトラブルにあなたを取得します可能性があります。
限り、ベクターのサイズを変更しない(あるいはあなたがリサイズに対処するように注意している)として、あなただけの罰金直接ポインタの書き込みを行うことができますので、私は自分のバッファのためのstd ::ベクトルを使用しています。私がのstd ::文字列としてデータの一部を必要とする場合、私はそれをコピーする必要がありますが、読み込みコールバックを超えて続くことが必要である私は私のリードバッファに対処する方法、何も関わらず、アウトコピーする必要があります。
シンプルな答えは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;
}
タスクのための非常に簡潔なコードを与えるます。
私はそれがより多くのようだと思います:
streambuf.commit( number_of_bytes_read );
istream istr( &streambuf );
string s;
istr >> s;
私はbasic_streambuf
コードに見ていないが、私はそれを文字列に一つだけのコピーであるべきと考えています。
私が最初に答えをテストし、「G ++ -std = C ++ 11」を使用してコンパイルするとき、コンパイラのエラーを得ました どのような私のために働いていたことだった。
#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();
これは、コンパイルして実行しました。