C++ 如何在不复制的情况下将std::string的一部分放入streambuf?
我最近经常使用boost-asio,我发现我经常使用C++ 如何在不复制的情况下将std::string的一部分放入streambuf?,c++,boost,boost-asio,stdstring,streambuf,C++,Boost,Boost Asio,Stdstring,Streambuf,我最近经常使用boost-asio,我发现我经常使用std::strings和asio::streambufs。我发现,作为解析网络数据的一部分,我试图在streambufs和strings之间来回获取数据。一般来说,我不想乱搞“格式化io”,所以iostreams不是很有用。我发现,ostream::operator()会损坏我的streambufs的内容(因为它是“格式化的”),这是您所期望的 在我看来,标准库确实缺少了大量迭代器和流对象来处理streambufs和strings以及未格式化
std::string
s和asio::streambuf
s。我发现,作为解析网络数据的一部分,我试图在streambuf
s和string
s之间来回获取数据。一般来说,我不想乱搞“格式化io”,所以iostream
s不是很有用。我发现,ostream::operator()
会损坏我的streambuf
s的内容(因为它是“格式化的”),这是您所期望的
在我看来,标准库确实缺少了大量迭代器和流对象来处理streambuf
s和string
s以及未格式化io。例如,如果我想将字符串的子字符串
放入streambuf
,如何在不创建字符串
副本的情况下执行此操作?基本的全进全出传输可通过以下方式完成:
// 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;
}
如果我只想将streambuf
的一部分转换成字符串,这似乎非常困难,因为istreambuf\u迭代器
不是随机访问迭代器,也不支持算术:
// 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;
}
如果我不介意格式化io,我总是可以从streambuf
中提取部分string
s,但我介意-格式化io几乎从来都不是我想要的:
// 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;
}
如果我对难看的副本没意见,我可以生成一个子字符串,当然-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;
}
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;
}
我觉得我错过了一些罗塞塔石,如果我发现了它,处理std::string
和asio::streambuf
会容易得多。a是否应该放弃std::streambuf
接口,使用asio::mutable_buffer
,我可以从asio::streambuf::prepare()
中得到它
std::ios::binary
标志打开输入流,并使用is>>std::noskipws
outstream.write(s.begin()+start, length);
或者使用boost::string\u ref
:
outstream << boost::string_ref(s).instr(start, length);
说得太长了。我认为stringstreams不支持移动。我想我已经看到了一个增加这一点的提议。同时,字符串流并不是非常复杂,所以你可以自己写。我在回答中给出了一些提示,但实际上,在将来尝试针对一个特定的问题(当然,在搜索现有答案之后)。这个答案是如此的分歧,我认为一个带有“快速指针”的答案是我们所能做的。你是说ifstream吗?如何使用ios::binary打开通用istream?另外,std::noskipws在这里也没有帮助——它只是告诉istream不要跳过前导空格。istream仍将根据空格标记输入。@TEDMidletonistream\u迭代器
,例如,将返回所有字符,以及包含在noskipws
中的空格。我说的是任何具体的istream&
实例,是的,我显然遗漏了一些东西。如何使用ios::binary打开通用istream?你能发布实际代码吗?istream没有支持此功能的ctor,而且我找不到任何可以将istream注释为“ios::binary”的访问器。因此,我谈论的是具体的istream&
实例,而不是istream
实例。我还确认了“是”,以回答“您在谈论ifstream吗”(尽管范围比文件更广)。我已经尝试从我的答案措辞中消除混淆。std::copy(it1,it2,ostreambuf_迭代器(os));这正是我想要的。谢谢
message=abcdefghijk lmnopqrs tuvwxyz
part_message=abcdefg
sbuf_it_wholestr=abcdefg
// 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;
}
line1=abcdefghijk lmnopqrs tuvwxyz
line2=1234 5678
outstream.write(s.begin()+start, length);
outstream << boost::string_ref(s).instr(start, length);
std::copy(it1, it2, ostreambuf_iterator<char>(os));