C++ ios::exceptions 在一切正常时抛出异常

标签 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 */} 。我试过了,没有任何区别。在我执行这些抛出用户定义类的任务之前。这次我决定为此尝试使用标准库,但似乎我遗漏了一些东西。

最佳答案

问题是 std::ios_base::failbit 在到达文件末尾时被设置:行读取正常。然而,一旦没有更多行,std::ios_base::failbit 将被设置:that 是检测结束条件的方式。结果,只有第一个文件被读取。

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

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

因为你应该总是检查是否有东西在之后尝试读取,条件while (ifs[i]->eof()) 是不明智的(这是一个很好的例子,为什么你应该使用 cplusplus.com 而是 cppreference.com )。相反,你应该使用

while (std::getline(*ifs[i], line))

在各自的 try/catch block 中读取每个文件可能会获得更好的结果。就个人而言,我认为异常和 I/O 不能很好地结合在一起,而且我从来没有让任何生产代码设置异常掩码。我建议不要为流设置异常掩码。

关于C++ ios::exceptions 在一切正常时抛出异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34843944/

相关文章:

c++ - opengl - 显示图像剪切

c++ - Boost.Coroutine 和 Boost.Coroutine2 的区别

c++ - C++11 中的作用域(失败)?

c++ - 类中的 ifstream 变量

c++ - 双图插入问题

c++ - 为什么不将类型名模板参数隐式识别为类型?

c# - 从 MS Access 数据库获取 Long 后使用 OleDbDataReader.GetInt64() 时出现 System.InvalidCastException

C++ dynamic_cast 异常

c++ - 具有 ifstream 成员的内部类的构造函数返回无效的 fstream

c++ - 无法初始化 ifstream "Error reading characters of string"