fstream:检查错误的最正确方法

fstream: the most correct way to check for errors

本文关键字:方法 检查 错误 fstream      更新时间:2023-10-16

我想围绕fstream类编写一个包装器。正如我所看到的,检查流是否正常工作的最常见方法是查看good()函数的结果。然而,我听说这主要是历史函数,使用它并不安全(更准确地说,可能会有一些情况下,流工作不好,但函数返回true。所以我想分享经验,并从其他人那里知道什么是检查fstream错误的最正确方法。

如果有可能检查不同类型的错误,比如文件不存在、只能打开读取等,那就太好了。也有必要让这些程序跨平台运行(然而,主要目标是Linux)。

提前感谢!

如果文件操作失败,eof()返回false,则可以检查errnoGetLastError(取决于平台)以找出问题所在。

我实际上只有两个建议,它们都依赖于用重载的!运算符的返回值检查打开的流。使用仅输入模式,只需检查文件是否存在:

char name[] = "C:\some_folder\some file.txt";
std::ifstream f;
f.open(name, std::ios::in);
if (!f)
    printf("File does not exist, or inadequate permissions");
f.close();

以输入/输出模式打开,以防止在计划执行写入操作时被截断:

std::fstream f;
f.open(name, std::ios::in | std::ios::out);
if (!f)
    printf("Could not open file");
f.close();

默认情况下,这些是相应流的输入参数,但为了澄清起见,我已经明确显示了它们。

在检查eof等的读/写操作期间,这个问题的第一个答案看起来很有见地。

good()/bad()只测试badbit,它只涵盖一些,并且大多数是不可恢复的错误。要检查错误,您需要同时检查failbitbadbit。有关何时设置这些位的更多详细信息,请参阅iosstate

要检查错误,请使用fail(),它同时检查failbitbadbit:

  if (stream.fail()) { /* handle error ... */ }

C++流还重载运算符bool以返回!fail(),因此您可以简单地执行

  if (!stream) { /* handle error ... */ }

然后您可以从errno中获得最后一个错误,并使用strerror():将其转换为文本

  std::ifstream f("my_file");
  if (!f) {
      std::cerr << std::strerror(errno) << std::endl;
      return 1;
  }

请注意,failbit包括eofbit(从某种意义上说,尝试在EOF下读取将设置两个位),因此要检查读取错误,需要排除eofbit:

  std::string line;
  while (std::getline(f, line)) {
      // process line
  }
  if (!f && !f.eof()) {
      std::cerr << std::strerror(errno) << std::endl;
  }