在 C++ 中捕获文件 IO 期间所有错误的最佳实践是什么?更具体地说,处理 ios 对象可能出现的错误的最佳做法是什么?例如,下面的程序从磁盘读取一个文件并打印它:
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include <exception>
#include <stdexcept>
// Defines a custom exception
struct MyException : public std::exception {
std::string s;
MyException(std::string s_) : s(s_) {};
const char * what () const throw () {
return ("MyException: " + s).c_str();
}
};
// Prints out nested exceptions
void print_exception(std::exception const & e, size_t const level = 0) {
std::cerr << std::string(level, ' ') << "exception: " << e.what() << '\n';
try {
std::rethrow_if_nested(e);
} catch(const std::exception& e) {
print_exception(e, level+1);
} catch(...) {}
}
// Read the specified filename into a string
std::string read_into_string(std::string const & fname) {
// Create the file stream
std::ifstream fin;
fin.exceptions(std::ifstream::failbit | std::ifstream::badbit);
// Open the file
try {
fin.open(fname.c_str());
} catch(...) {
std::throw_with_nested(MyException(
"Unable to open the file: " + fname));
}
// Make sure to close out the file if there's a problem
try {
// Create the string stream
std::stringstream sin;
sin.exceptions(std::ifstream::failbit | std::ifstream::badbit);
// Put the file stream into a string stream
try {
sin << fin.rdbuf();
} catch(...) {
std::throw_with_nested(MyException(
"Error when pusing the file stream into the string stream"));
}
// Turn the string stream into a string
std::string str;
try {
str = sin.str();
} catch(...) {
std::throw_with_nested(MyException(
"Error converting the string stream into a string"));
}
// Close out the file
fin.close();
// Return the string;
return str;
} catch(...) {
// Close out the file
fin.close();
// Rethrow the exception
throw;
}
}
int main() {
try {
std::string str(read_into_string("file.txt"));
std::cout << str;
} catch(const std::exception& e) {
print_exception(e);
}
}
但是,它看起来非常非常重。基本上,似乎我们每次触摸 ios 对象时都必须检查,因为可能会出现问题,这有助于准确了解错误的位置。此外,上面的代码包含多个文件关闭,一个是一切正常,另一个是异常,这是不可取的。最后,我没有检查其他 ios 对象(如 cout)的错误状态,但从技术上讲,因为它们是 ios 对象,它们不能设置一个应该被捕获的错误或失败位吗?如果出现错误,是否需要关闭字符串流?
实际上,核心问题是:处理 ios 对象可能出现的错误的最佳做法是什么?
最佳答案
在 C++ 中的 I/O 流上启用 .exceptions()
并不是常见的做法。很可能你学过其他语言,他们教你尽可能使用异常。 不要。
毫无异常(exception)地处理流上的错误非常容易:流将从真实变为虚假。此外,除非您重置失败位,否则对虚假流的任何操作都将完全无效。
此外,还有一种将整个输入流转储到输出流的方法。
// Read the specified filename into a string
std::string read_into_string(std::string const & fname) {
// Create the file stream
std::ifstream fin(fname.c_str());
std::ostringstream oss;
oss << fin.rdbuf();
if (!fin) throw MyException();
return oss.str();
}
但是,您可能需要重新考虑在单个流中输入的需求。通常我发现一系列的行更有用。
关于c++ - 捕获 C++ 文件 IO 期间所有错误(或 ios 对象中的任何错误)的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26223489/