正确方式是用 std::ios::app 模式打开文件实现追加写入,它自动定位文件末尾且不覆盖原内容;需注意换行与手动刷新缓冲区以防日志错乱或丢失。

用 std::ofstream 以 std::ios::app 模式打开文件
直接追加写入,核心是打开文件时指定 std::ios::app 标志。它会自动将文件指针定位到末尾,且每次写入前不擦除原有内容。注意:std::ios::app 隐含 std::ios::out,无需额外指定输出模式。
常见错误是只用 std::ios::out,这会导致覆盖原文件;或误加 std::ios::trunc(会清空文件)。
-
std::ofstream file("log.txt", std::ios::app);—— 正确,追加写入 -
std::ofstream file("log.txt");—— 错误,默认覆盖 -
std::ofstream file("log.txt", std::ios::out | std::ios::app);—— 等价于上一条,冗余但合法
追加写入时要注意换行和缓冲
如果前一次写入没结尾换行,新内容会紧贴在上一行末尾,导致日志格式错乱。另外,std::ofstream 默认行缓冲不生效(尤其重定向到文件时),需手动 flush() 或用 std::endl 触发刷新,否则程序崩溃或异常退出时可能丢失最后几条记录。
示例:
立即学习“C++免费学习笔记(深入)”;
std::ofstream log("output.txt", std::ios::app);
log << "Result: " << 42 << std::endl; // 推荐:自动 flush + 换行
// 或
log << "Result: " << 42 << "\n";
log.flush(); // 手动确保落盘
多线程环境下不能直接共享同一个 std::ofstream
多个线程共用一个 std::ofstream 对象写入,会导致数据交错、乱码甚至崩溃——C++ 标准库流对象不是线程安全的。不要试图用全局 ofstream 实现日志追加。
- 每个线程单独打开/关闭文件(开销略大,但安全)
- 用互斥锁保护单个流对象(必须保证锁粒度覆盖整个写入操作,包括
<<和flush) - 更推荐:用无锁队列收集日志,由单个日志线程统一追加写入
追加失败的典型原因和排查点
写入失败往往不是代码逻辑问题,而是环境权限或路径问题。调用 file.is_open() 或 file.good() 必须检查,否则静默失败。
- 路径不存在且父目录不可写 ——
ofstream不会自动创建中间目录,只创建最后一级文件 - 文件被其他进程独占打开(如 Excel 正在编辑该 CSV)—— Windows 下会直接打开失败
- 磁盘满或配额超限 ——
file.fail()为 true,但errno可能未被流对象更新,建议结合std::filesystem::space()提前校验 - 使用相对路径时,工作目录和预期不一致 —— 建议用绝对路径或显式
std::filesystem::current_path()调试
std::ios::app 这一个参数。


















