用 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 或第三方库。