我使用<<
流操作符实现了一个对象的反序列化例程。该例程本身使用istreambuf_iterator<char>
来逐个从流中提取字符,以构建该对象。关于`std :: istreambuf_iterator`的使用感到困惑
最终,我的目标是能够使用istream_iterator<MyObject>
迭代流并将每个对象插入vector
。漂亮的标准,除非我在获取istream_iterator
到停止遇到码流结束时迭代。现在,它只是永远循环播放,即使拨打表示我在文件末尾。
这里的代码来重现问题:
struct Foo
{
Foo() { }
Foo(char a_, char b_) : a(a_), b(b_) { }
char a;
char b;
};
// Output stream operator
std::ostream& operator << (std::ostream& os, const Foo& f)
{
os << f.a << f.b;
return os;
}
// Input stream operator
std::istream& operator >> (std::istream& is, Foo& f)
{
if (is.good())
{
std::istreambuf_iterator<char> it(is);
std::istreambuf_iterator<char> end;
if (it != end) {
f.a = *it++;
f.b = *it++;
}
}
return is;
}
int main()
{
{
std::ofstream ofs("foo.txt");
ofs << Foo('a', 'b') << Foo('c', 'd');
}
std::ifstream ifs("foo.txt");
std::istream_iterator<Foo> it(ifs);
std::istream_iterator<Foo> end;
for (; it != end; ++it) cout << *it << endl; // iterates infinitely
}
我知道在这个简单的例子,我甚至都不需要istreambuf_iterator,但我只是想为了简化问题,所以它更可能人会回答我的题。
所以这里的问题是,即使istreambuf_iterator
到达流缓冲区的末尾,实际流本身也不会进入EOF
状态。调用istream::eof()
返回false,即使返回文件中的最后一个字节,并且istreambuf_iterator<char>(ifs)
与istreambuf_iterator<char>()
相比较,意味着我肯定在流的末尾。
我看着Iostreams库代码,看看它究竟是如何确定istream_iterator
是否处于末端位置,基本上它会检查是否istream::operator void*() const
计算结果为true
。这istream的库函数返回:
return this->fail() ? 0 : const_cast<basic_ios*>(this);
换句话说,它返回0
(假)如果failbit设置。然后它将该值与默认构建的实例istream_iterator
中的相同值进行比较,以确定我们是否在最后。
所以我试着在我的std::istream& operator >> (std::istream& is, Foo& f)
例程中手动设置失败位,当istreambuf_iterator
与最终迭代器比较真时。这工作完美,并正确终止循环。但现在我真的很困惑。看来,istream_iterator
肯定检查std::ios::failbit
为了表示“流结束”条件。但是,这不是std::ios::eofbit
的用途吗?我认为failbit
是出于错误条件,例如,如果fstream
的底层文件无法打开或某事。
那么,为什么我需要拨打istream::setstate(std::ios::failbit)
才能让循环终止?
循环永久指示流已经变质。问题是为什么? – 2010-11-11 01:50:04
@Martin,好吧,即使我用'std :: stringstream'替换文件流,也会发生同样的问题。所以这不能是某种低级文件相关的问题。 – Channel72 2010-11-11 01:53:57
阅读@ PigBen的回答。原因是在外层你使用istream_iterator(在for_each)和istreambuf_iterator在内部(operatro >>)。您的使用需要保持一致。在这两种情况下使用istreambuf_iterators,它应该工作。 – 2010-11-11 18:17:08