这是来自 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/