用 std::ifstream 安全读取文本文件的关键是检查打开失败而非能否打开,需用 is_open() 或流对象布尔判断;默认以 ios::in 模式打开,不支持写入;推荐 std::getline() 逐行读取,避免 >> 读字符串。

直接用 std::ifstream 和 std::ofstream 就能完成绝大多数文件读写需求,不需要手动管理缓冲区或系统调用。
如何用 std::ifstream 安全读取文本文件
关键不是“能不能打开”,而是“打开失败时程序是否崩溃”。必须检查 is_open() 或直接用流对象作布尔判断。
-
std::ifstream默认以std::ios::in模式打开,不支持写入;若文件不存在或无权限,构造后流状态为failbit - 逐行读推荐用
std::getline(),它会自动丢弃换行符,且不会因空行中断 - 避免用
>>运算符读字符串——遇到空格/制表符就停,且无法区分读到末尾还是格式错误
std::ifstream fin("data.txt");
if (!fin) { // 等价于 if (fin.fail())
std::cerr << "无法打开 data.txt\n";
return;
}
std::string line;
while (std::getline(fin, line)) {
std::cout << line << "\n";
}
如何用 std::ofstream 控制写入行为(覆盖 vs 追加)
默认是覆盖写入,想追加必须显式指定 std::ios::app 模式;但要注意:app 模式下所有写入都强制定位到文件末尾,seekp() 无效。
- 覆盖写:直接构造
std::ofstream("out.txt"),或显式传std::ios::out - 追加写:必须用
std::ofstream("out.txt", std::ios::app) - 清空并重写:先用
std::ofstream("out.txt", std::ios::trunc),但trunc是默认行为,通常不用显式写
std::ofstream fout("log.txt", std::ios::app); // 追加模式
if (fout) {
fout << "new entry at " << std::time(nullptr) << "\n";
}
二进制读写必须用 std::ios::binary 标志
不加 binary 模式,在 Windows 上读写二进制文件会导致 \r\n 被悄悄转成 \n(或反之),数据损坏。这是跨平台开发中最常被忽略的坑。
立即学习“C++免费学习笔记(深入)”;
- 读二进制:用
std::ifstream("file.dat", std::ios::binary)+read() - 写二进制:用
std::ofstream("file.dat", std::ios::binary)+write() -
read()和write()的第二个参数是字节数,不是元素个数;对结构体写入要确保没有内存对齐填充干扰
struct Record { int id; double value; };
Record r = {42, 3.14};
std::ofstream binout("data.bin", std::ios::binary);
binout.write(reinterpret_cast(&r), sizeof(r));
关闭文件和异常处理的实用建议
fstream 对象析构时会自动关闭文件,所以局部变量一般不用手动调 close();但如果你需要立刻释放句柄、或检查写入是否真正落盘,则必须调 close() 并检查其返回值。
-
close()失败可能意味着磁盘满、权限丢失或 I/O 错误,仅靠析构无法捕获这类问题 - 不要依赖
exceptions()开启异常——它会让流在任何状态位变化时抛异常(包括eofbit),反而难处理 - 更稳妥的做法是每次操作后查
good()/fail()/bad(),尤其在循环中
std::ofstream fout("tmp.txt");
fout << "hello";
if (!fout.good()) {
std::cerr << "写入失败\n";
}
fout.close(); // 此时才真正 flush 并检查底层错误
if (!fout.good()) {
std::cerr << "close 失败,可能未写入磁盘\n";
}
文件路径中的反斜杠在 C++ 字符串里要写成双反斜杠 "C:\\data\\input.txt",或者用原始字符串字面量 R"(C:\data\input.txt)";另外,fstream 不支持 Unicode 路径(如含中文名),Windows 下需改用 _wfopen 或第三方库。









