37

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

有没有其他方法可以在不过度复制的情况下创建带有 streambufs 内容的字符串?

4

11 回答 11

50

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

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上面的意思是表示 a streambuf*,因此请酌情取其地址。还要注意最后一个示例中第一个参数周围的附加括号,以便它不会将其解释为返回字符串并采用迭代器和另一个函数指针的函数声明(“最令人烦恼的解析”)。

于 2009-05-18T14:42:34.520 回答
48

真的隐藏在文档中......

给定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);
于 2012-12-08T19:44:08.923 回答
24

另一种可能性boost::asio::streambufboost::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);

这不适用于普通的流缓冲区,并且可能被认为是脏的,但它似乎是最快的方法。

于 2009-05-19T15:22:12.163 回答
15

因为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

于 2012-10-17T12:07:16.880 回答
2

也可以通过以下方式获取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);
于 2013-07-01T10:13:33.500 回答
1

您只能从 std::string 创建 const_buffer 的原因是 std::string 在其合同中明确不支持直接基于指针的写入。你可以做一些邪恶的事情,比如将你的字符串调整到一定的大小,然后 const_cast 来自 c_str() 的常量并将其视为原始 char* 缓冲区,但这很顽皮,总有一天会给你带来麻烦。

我将 std::vector 用于我的缓冲区,因为只要向量不调整大小(或者您小心处理调整大小),您就可以直接写入指针就可以了。如果我需要一些数据作为 std::string,我必须将其复制出来,但是我处理读取缓冲区的方式,任何需要持续超出读取回调的内容都需要复制出来。

于 2009-06-12T07:23:55.737 回答
1

我没有看到将 n 字符准确读入 a 的现有答案std::stringstream,因此可以这样做:

std::stringstream ss;
boost::asio::streambuf sb;
const auto len = 10;

std::copy_n(boost::asio::buffers_begin(sb.data()), len,
            std::ostream_iterator<decltype(ss)::char_type>(ss));

编译器资源管理器

于 2021-03-20T21:26:21.410 回答
0

一个更简单的答案是将其转换为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;
}

为任务提供非常简洁的代码。

于 2016-11-11T08:13:20.410 回答
0

我大多不喜欢说“你不想要 X,你想要 Y,这是如何做 Y”的答案,但在这种情况下,我很确定我知道 tstenner 想要什么。

在 Boost 1.66 中,添加了动态字符串缓冲区类型,因此async_read可以直接调整大小并写入字符串缓冲区。

于 2020-05-27T06:53:33.243 回答
-1

我测试了第一个答案,并在使用“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(); 

这编译并运行。

于 2016-06-24T02:42:19.110 回答
-2

我觉得更像是:


streambuf.commit( number_of_bytes_read );

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

我没有查看basic_streambuf代码,但我相信这应该只是字符串的一个副本。

于 2009-05-18T14:56:43.010 回答