当它击中eof时std :: getline投掷

时间:2012-08-04 10:21:59

标签: c++ fstream eof getline

std::getline在获得eof时抛出异常。 这就是我的工作方式。

std::ifstream stream;
stream.exceptions(std::ifstream::failbit|std::ifstream::badbit);
try{
  stream.open(_file.c_str(), std::ios_base::in);
}catch(std::ifstream::failure e){
  std::cout << "Failed to open file " << _file.c_str() << " for reading" << std::endl;
}
while(!stream.eof()){
  std::string buffer = "";
  std::getline(stream, buffer);
  //process buffer
  //I do also need to maintain state while parsing
}

在上面的代码getline中,eof会抛出异常std::string buffer = ""; while(std::getline(stream, buffer)){ //also causes getline to hit eof and throw } 如何处理这种情况?

修改

{{1}}

2 个答案:

答案 0 :(得分:13)

您可以在代码的最开头激活流的异常处理:

stream.exceptions(std::ifstream::failbit|std::ifstream::badbit);

现在,如果提取格式化数据(如浮点值,整数或字符串)失败,它将设置failbit:

eofbit    indicates that an input operation reached the end of an 
          input sequence;
failbit   indicates that an input operation failed to read the expected 
          characters, or that an output operation failed to generate the 
          desired characters.

虽然getline(stream,buffer)确实会设置eofbit,如果它到达文件的末尾,它也会设置failbit,因为无法提取所需的字符(一行)。

在循环中包装另一个try-catch-block或禁用failbit异常。

实施例

#include <iostream>
#include <fstream>

int main(){
  std::ifstream stream("so.cc");
  stream.exceptions(std::ifstream::failbit|std::ifstream::badbit);
  std::string str;

  try{
    while(std::getline(stream, str));
  }catch(std::ifstream::failure e){
    std::cerr << "Exception happened: " << e.what() << "\n"
      << "Error bits are: "
      << "\nfailbit: " << stream.fail() 
      << "\neofbit: " << stream.eof()
      << "\nbadbit: " << stream.bad() << std::endl;    
  }
  return 0;
}

结果:

Exception happened: basic_ios::clear
Error bits are:
failbit: 1
eofbit: 1
badbit: 0

请注意 eofbitfailbit都已设置。

另见:

答案 1 :(得分:0)

正如您所说,当流当前位于文件末尾的空白行时调用getline将同时设置eofbit(因为它到达文件末尾)和failbit(因为无法提取任何内容,甚至不能提取)行定界符)。

因此,如果已将流设置为在设置failbit时引发异常,则在读取该空白行时会引发异常。

为防止这种情况,您可以在调用getline之前在流中偷看下一个字符:

std::string buffer = "";
while(stream.peek() != EOF && std::getline(stream, buffer)){
    //do something with the buffer
}