我最近经常使用 boost asio,我发现我正在使用std::string
s 和asio::streambuf
s 相当多。streambuf
作为解析网络数据的一部分,我发现我正在尝试在s 和string
sa之间来回获取数据。一般来说,我不想乱用“格式化 io”,所以iostream
s 不是很有用。我发现,ostream::operator<<()
尽管有官方文档,但似乎将 my string
s传递给streambuf
s 不受干扰,istream::operator>>()
破坏了 my streambuf
s 的内容(正如您所期望的那样,因为它是“格式化的”)。
在我看来,标准库确实缺少大量迭代器和流对象来处理streambuf
s 和string
s 以及未格式化的 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::iterator
s 将 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::string
会asio::streambuf
容易得多。是否应该放弃std::streambuf
界面并使用asio::mutable_buffer
,我可以摆脱asio::streambuf::prepare()
?