当一切都很好时,C ++ ios :: exceptions会抛出异常

时间:2016-01-17 21:29:15

标签: c++ exception ifstream

以下是cplusplus.com/reference

中的代码
#include <iostream>     // std::cerr
#include <fstream>      // std::ifstream

int main () {
  std::ifstream file;
  file.exceptions ( std::ifstream::failbit | std::ifstream::badbit );
  try {
    file.open ("test.txt");
    while (!file.eof()) file.get();
    file.close();
  }
  catch (std::ifstream::failure e) {
    std::cerr << "Exception opening/reading/closing file\n";
  }

  return 0;
}

我的代码非常相似

int main()
{
    std::vector<int> numbers;
    std::vector<std::ifstream *> ifs;
    std::array<std::string, 3> files = {
        "f1.txt", "f2.txt", "f3.txt"
    };
    for (int i = 0; i < files.size(); ++i) {
        std::ifstream *_ifs = new std::ifstream;
        ifs.push_back(_ifs);
        ifs[i]->exceptions( std::ifstream::failbit | std::ifstream::badbit );
    }

    try {
        int n;
        std::string line;
        for (int i = 0; i < files.size(); ++i) {
            ifs[i]->open(files[i]);
            while (!ifs[i]->eof()) {
                std::getline(*ifs[i], line);
                std::istringstream iss(line);
                while (iss >> n) {
                    if (n % 3 == 0 && n % 5 == 0 && n % 7 == 0)
                        numbers.push_back(n);
                }

            }
            ifs[i]->close();
        }
    } catch (std::ifstream::failure e) {
        std::cerr << "Error reading from files: " << e.what() << std::endl;
        return 1;
    }
    for (int i = 0; i < ifs.size(); ++i)
        delete ifs[i];
    ifs.clear();
    std::cout << "Files have been read\n";

 // Do something with numbers
 // ...

}

问题在于没有阅读。几乎立即抛出异常。如果我从异常中注释掉failbit,一切正常,但在Windows上缺少文件时不会抛出异常。在Ubuntu上,如果文件丢失,则抛出没有failbit个异常,并且所有内容都被正确读取。但是在Ubuntu上使用failbit也会在读取开始时抛出异常并且不会读取任何内容。我试着去谷歌吧。从cplusplus.com找到了这个例子。而stackoverflow问题的答案不是检查eof,而是以这种方式阅读while(getline(ifs, line)) { /* do something with line */ }。我试过这个,没有区别。在我做这些任务之前抛出用户定义的类。这次我决定尝试标准库,看起来我错过了什么。

1 个答案:

答案 0 :(得分:1)

问题是当到达文件末尾时std::ios_base::failbit被设置:读取行正常。但是,一旦没有其他行std::ios_base::failbit将被设置: 是检测结束条件的方式。因此,只读取第一个文件。

如果您在阅读文件的循环中输出了内容,您会看到实际读取了这些行。由于您过滤了读取的值,因此我猜您没有看到任何数字,因为所提供的数字都不符合条件。

eof()的检查当然没有帮助,因为阅读最后一行将在到达文件末尾之前使用换行符停止阅读,但它不会设置{{ 1}}:该位仅在实际触摸EOF时设置,但仅在读取下一个字符时发生。

由于总是检查在尝试阅读之后是否已读取,因此条件std::ios_base::eofbit是不明智的(这是一个很好的例子,为什么你应该使用cplusplus.com,而是使用cppreference.com)。相反,你应该使用

while (ifs[i]->eof())

您可以通过阅读自己的while (std::getline(*ifs[i], line)) / try块中的每个文件获得更好的结果。就个人而言,我不认为异常和I / O很好地配合在一起,我从来没有任何生产代码设置异常掩码。我建议不要为流设置异常掩码。