以下是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 */ }
。我试过这个,没有区别。在我做这些任务之前抛出用户定义的类。这次我决定尝试标准库,看起来我错过了什么。
答案 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很好地配合在一起,我从来没有任何生产代码设置异常掩码。我建议不要为流设置异常掩码。