显然 boost::asio::async_read 不喜欢字符串,因为它是唯一的重载 boost::asio::buffer 让我能够创造 const_buffers,所以我不得不将所有内容读入流缓冲区。
现在我想将streambuf的内容复制到一个字符串中,但它显然只支持写入char*(sgetn()),使用streambuf创建一个istream并使用 getline().

有没有其他方法可以使用streambufs内容创建字符串而无需过多复制?

有帮助吗?

解决方案

我不知道这是否算作“过度复制的”,但您可以使用一个字符串流:

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

请注意上面someStreamBuf旨在表示一个streambuf*,所以采取其地址为适当。还注意到围绕在最后一个例子的第一个参数的附加括号,使得它不将其解释为函数声明返回一个串并考虑迭代器和另一个函数指针(“最棘手的解析”)。

其他提示

它是 真的 埋葬 在文档中...

给定 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

人们也可以从使用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 :: string const_buffer的原因是因为的std :: string明确不支持其合同直接基于指针的写作。你可以做一些邪恶的类似调整您的字符串到一定规模,然后从const_cast会c_str(常量性),并把它像一个原始的char *缓冲区,但这是个非常顽皮,将会给你带来麻烦的一天。

我使用std :: vector的我缓冲区,因为只要载体不调整(或你小心应对调整),你可以做直接指针写就好了。如果我需要一些数据作为的std :: string的,我必须把它复制出来,但需要持续超越读回调我处理我读缓冲区的方式,有什么需要,无论被拷贝出来。

有一个简单的答案是将其转换成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(); 

此编译和运行。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top