1

我最近经常使用 boost asio,我发现我正在使用std::strings 和asio::streambufs 相当多。streambuf作为解析网络数据的一部分,我发现我正在尝试在s 和stringsa之间来回获取数据。一般来说,我不想乱用“格式化 io”,所以iostreams 不是很有用。我发现,ostream::operator<<()尽管有官方文档,但似乎将 my strings传递给streambufs 不受干扰,istream::operator>>()破坏了 my streambufs 的内容(正如您所期望的那样,因为它是“格式化的”)。

在我看来,标准库确实缺少大量迭代器和流对象来处理streambufs 和strings 以及未格式化的 io。例如,如果我想将 a 的子字符串string放入 astreambuf中,如何在不创建 的副本的情况下做到这一点string?一个基本的全进全出转移可以像这样完成:

// Get a whole string into a streambuf, and then get the whole streambuf back
//  into another string
{
    boost::asio::streambuf sbuf;
    iostream os(&sbuf);
    string message("abcdefghijk lmnopqrs tuvwxyz");
    cout << "message=" << message << endl;
    os << message;
    std::istreambuf_iterator<char> sbit(&sbuf);
    std::istreambuf_iterator<char> end;
    std::string sbuf_it_wholestr(sbit, end);
    cout << "sbuf_it_wholestr=" << sbuf_it_wholestr << endl;    
}

印刷:

message=abcdefghijk lmnopqrs tuvwxyz
sbuf_it_wholestr=abcdefghijk lmnopqrs tuvwxyz

如果我只想将 a 的一部分streambuf放入字符串中,那似乎真的很难,因为istreambuf_iterator它不是随机访问迭代器并且不支持算术:

// Get a whole string into a streambuf, and then get part of the streambuf back
//  into another string. We can't do this because istreambuf_iterator isn't a
//  random access iterator!
{
    boost::asio::streambuf sbuf;
    iostream os(&sbuf);
    string message("abcdefghijk lmnopqrs tuvwxyz");
    cout << "message=" << message << endl;
    os << message;
    std::istreambuf_iterator<char> sbit(&sbuf);
    // This doesn't work
    //std::istreambuf_iterator<char> end = sbit + 7; // Not random access!
    //std::string sbuf_it_partstr(sbit, end);
    //cout << "sbuf_it_partstr=" << sbuf_it_partstr << endl;    
}    

而且似乎没有任何方法可以直接使用string::iterators 将 a 的一部分转储string到 a中streambuf

// istreambuf_iterator doesn't work in std::copy either
{
    boost::asio::streambuf sbuf;
    iostream os(&sbuf);
    string message("abcdefghijk lmnopqrs tuvwxyz");
    cout << "message=" << message << endl;
    std::istreambuf_iterator<char> sbit(&sbuf);
    //std::copy(message.begin(), message.begin()+7, sbit); // Doesn't work here
}    

如果我不介意格式化 io,我总是可以string从 a 中提取部分 s ,但我愿意——格式化的 io 几乎从来都不是我想要的:streambuf

// Get a whole string into a streambuf, and then pull it out using an ostream
// using formatted output
{
    boost::asio::streambuf sbuf;
    iostream os(&sbuf);
    string message("abcdefghijk lmnopqrs tuvwxyz");
    cout << "message=" << message << endl;
    string part1, part2;
    os << message;
    os >> part1;
    os >> part2;
    cout << "part1=" << part1 << endl;    
    cout << "part2=" << part2 << endl;    
}

印刷:

message=abcdefghijk lmnopqrs tuvwxyz
part1=abcdefghijk
part2=lmnopqrs

如果我对丑陋的副本没问题,我当然可以生成一个子字符串 -std::string::iterator 随机访问......

// Get a partial string into a streambuf, and then pull it out using an
//  istreambuf_iterator
{
    boost::asio::streambuf sbuf;
    iostream os(&sbuf);
    string message("abcdefghijk lmnopqrs tuvwxyz");
    cout << "message=" << message << endl;
    string part_message(message.begin(), message.begin()+7);
    os << part_message;
    cout << "part_message=" << part_message << endl;
    std::istreambuf_iterator<char> sbit(&sbuf);
    std::istreambuf_iterator<char> end;
    std::string sbuf_it_wholestr(sbit, end);
    cout << "sbuf_it_wholestr=" << sbuf_it_wholestr << endl;    
}

印刷:

message=abcdefghijk lmnopqrs tuvwxyz
part_message=abcdefg
sbuf_it_wholestr=abcdefg

stdlib 也有奇怪的独立的std::getline(),它可以让你拉出单独的行ostream

// If getting lines at a time was what I wanted, that can be accomplished too...          
{    
    boost::asio::streambuf sbuf;
    iostream os(&sbuf);
    string message("abcdefghijk lmnopqrs tuvwxyz\n1234 5678\n");
    cout << "message=" << message << endl;
    os << message;
    string line1, line2;
    std::getline(os, line1);
    std::getline(os, line2);
    cout << "line1=" << line1 << endl;
    cout << "line2=" << line2 << endl;
}

打印:消息=abcdefghijk lmnopqrs tuvwxyz 1234 5678

line1=abcdefghijk lmnopqrs tuvwxyz
line2=1234 5678

我觉得我错过了一些罗塞塔石碑,如果我发现了它,处理起来std::stringasio::streambuf容易得多。是否应该放弃std::streambuf界面并使用asio::mutable_buffer,我可以摆脱asio::streambuf::prepare()

4

1 回答 1

2
  1. istream::operator>>() 破坏了我的流缓冲区的内容(正如您所期望的那样,因为它是“格式化的”)。

    std::ios::binary使用标志打开您的输入流并使用is >> std::noskipws

  2. 例如,如果我想将字符串的子字符串放入 streambuf,如何在不创建字符串副本的情况下做到这一点?一个基本的全进全出转移可以像这样完成

    试试喜欢

     outstream.write(s.begin()+start, length);
    

    或使用boost::string_ref

     outstream << boost::string_ref(s).instr(start, length);
    

  3. 而且似乎没有任何方法可以直接使用 string::iterators 将部分字符串转储到 streambuf 中:

     std::copy(it1, it2, ostreambuf_iterator<char>(os));
    
  4. 回覆。解析消息行:

    您可以使用iter_split.

    您可以使用动态解析嵌入式语法boost::spirit::istream_iterator

于 2014-11-28T20:30:13.297 回答