2013-01-13 70 views
2

我想从两个文件中读取,直到达到其中一个文件的末尾。 如果出现问题,fstream应抛出异常。C++ fstream:到达eof时抛出异常

问题是,当eof位被设置时,坏的或者失败的位也被设置。

ifstream input1; 
input1.exceptions(ios_base::failbit | ios_base::badbit); 
input1.open("input1", ios_base::binary | ios_base::in); 

ifstream input2; 
input2.exceptions(ios_base::failbit | ios_base::badbit); 
input2.open("input2", ios_base::binary | ios_base::in); 

ofstream output; 
output.exceptions(ios_base::failbit | ios_base:: badbit); 
output.open("output", ios_base::binary | ios_base::out | ios_base::trunc); 

char in1, in2, out; 

while(!input1.eof() && !input2.eof()) { 
    input1.read((char*) &in1, 1); 
    input2.read((char*) &in2, 1); 
    out = in1^in2; 
    output.write((const char*) &out, 1); 
} 

input1.close(); 
input2.close(); 
output.close(); 

这导致

$ ./test 
terminate called after throwing an instance of 'std::ios_base::failure' 
    what(): basic_ios::clear 

如何做是正确的?

+2

我们是否假设“处理抛出异常的异常”这个明显的答案是不可能的? –

+0

做的输入文件存在吗? –

+3

可能的重复:http://stackoverflow.com/questions/6781545/why-failbit-set-when-eof-on-read-is-there-a-way-out – Csq

回答

4

您代码中的基本问题是FAQ。你永远不应该使用eof()作为读循环的测试条件,因为在C/C++(不像一些其他语言),直到您已经阅读过去文件的末尾,因此的身体eof()未设置为true循环将会输入一次太多次。

的地道正确的步骤是在循环条件读取操作本身,因此,出口处发生在正确的点:

while (input1.get(in1) && input2.get(in2)) { /* etc */ } 
    // here, after the loop, you can test eof(), fail(), etc 
    // if you're really interested in why the loop ended. 

此循环将与较小的输入文件的耗尽自然结束,这正是你想要的。

+1

谢谢,但这段代码仍然抛出异常时到达文件末尾。 – firefexx

+1

那是因为你为异常提供了答案。关键是你不需要任何异常来检测输入结束。 – arayq2

+1

此外,你真的不想在这个API中使用异常。参见例如[this](http://stackoverflow.com/questions/3180268/why-are-c-stl-iostreams-not-exception-friendly)以及上面的更新代码片段 – arayq2

0

只需删除.eof()if(fstream)检查所有位(eof坏和失败)。

因此重新编写,同时为:

while(input1 && input2) 

,然后也许验证EOF()在流的最后一个返回true。

希望这会有所帮助。

0

都不要抛出异常,并使用input1.readistream::get在while条件

while (input1.get(in1) && input2.get(in2)) { 
... 
} 

如果你读了你的循环体中的人物,你将有一个额外的字符在输出中,没有对应的输入字符。也许这就是你为什么首先使用std::ios::exeptions的原因。