代码之家  ›  专栏  ›  技术社区  ›  tstenner

将streambuf的内容复制到字符串

  •  30
  • tstenner  · 技术社区  · 17 年前

    显然 boost::asio::async_read 不喜欢字符串,因为它是 boost::asio::buffer 允许我创建 const_buffer 所以我一直在把所有的东西都读成流媒体。
    现在我想将streambuf的内容复制到一个字符串中,但它显然只支持写入char*( sgetn() ,使用streambuf创建IStream并使用 getline() .

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

    9 回复  |  直到 8 年前
        1
  •  44
  •   Johannes Schaub - litb    17 年前

    我不知道它是否算作 过度复制 “,但可以使用stringstream:

    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* ,因此,请将其地址视情况而定。还要注意最后一个示例中第一个参数周围的附加括号,这样它就不会将其解释为返回字符串并使用迭代器和另一个函数指针(“最麻烦的分析”)的函数声明。

        2
  •  37
  •   Christian Severin    8 年前

    它是 真的? 埋葬的 in the docs

    鉴于 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);
    
        3
  •  24
  •   tstenner    17 年前

    另一种可能性是 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);
    

    这不适用于普通的streambufs,可能会被认为是脏的,但这似乎是最快的方法。

        4
  •  13
  •   iericzhou    13 年前

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

        5
  •  1
  •   ArtemGr    13 年前

    也可以从 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);
    
        6
  •  0
  •   user121826    17 年前

    只能从std::string创建const缓冲区的原因是std::string显式不支持在其协定中直接基于指针的写入。你可以做一些邪恶的事情,比如将字符串的大小调整到一定的大小,然后const将constness从c_str()中抛出,并将其视为原始char*缓冲区,但这很淘气,总有一天会给你带来麻烦。

    我使用std::vector作为缓冲区,因为只要向量不调整大小(或者您小心处理大小调整),就可以直接编写指针。如果我需要一些作为std::string的数据,我必须将其复制出来,但是按照我处理读缓冲区的方式,需要持续到读回调之外的任何数据都需要复制出来,不管怎样。

        7
  •  0
  •   DevMac    9 年前

    一个简单的答案是把它转换成 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;
    }
    

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

        8
  •  -2
  •   Nikolai Fetissov    17 年前

    我觉得更像是:

    
    streambuf.commit( number_of_bytes_read );
    
    istream istr( &streambuf );
    string s;
    istr >> s;
    

    我还没有调查 basic_streambuf 代码,但我认为这应该只是字符串中的一个副本。

        9
  •  -2
  •   user5732391    10 年前

    在使用“g++-sd= 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(); 
    

    这是编译并运行的。

    推荐文章