用std::ios::app模式打开文件可安全追加写入,自动定位到末尾且原子性保障;不可混用trunc,需注意跨平台与多进程安全边界。
f
stream
用
模式打开文件就能追加写入
直接用
以
模式打开,所有写入操作自动定位到文件末尾,无需手动
。这是最安全、最符合语义的追加方式。
必须显式指定
,仅用
会覆盖原文件
隐含
,不用额外加
如果文件不存在,
模式会自动创建;存在则光标初始位置就在 EOF,写入即追加
不支持读取(
与
冲突),如需边读边追加,得用两个流或先读后写
常见错误:用
或
代替
有人试图用
模式 +
模拟追加,但容易出错:
只是把写入位置初始化到末尾,后续
或
仍可能覆盖——因为 C++ 流在非
模式下,写入会从当前位置开始,而多次写入之间位置不自动更新到新末尾
手动
后写入,若中间有其他流操作(比如另一线程/进程写入),位置会失效,导致覆盖或错位
模式由系统底层保证原子性追加(尤其在 POSIX 系统上等价于
),
+
没这保障
构造时传参的正确写法
推荐一次性构造并指定模式,避免默认构造后调用
的歧义:
C函数速查手册(CHM版)
C函数速查手册(CHM版)
下载
不要混用
和
——行为未定义,多数实现直接忽略
追加写入中文或特殊字符时,记得在打开前调用
(Linux/macOS)或
(Windows)确保编码适配
若需每次写入后立即落盘(比如日志防丢),调用
,但注意频繁 flush 会影响性能
多线程/多进程环境下追加的安全边界
在单进程内是线程安全的(C++11 起,
对同一
对象的调用有内部同步),但跨进程不保证:
立即学习
“
C++免费学习笔记(深入)
”;
Linux/macOS 下,
模式最终映射为
标志,内核保证每次
原子地追加,多个进程可安全共用同一文件
Windows 下行为依赖 CRT 实现,部分旧版本不完全等价于
,高并发写入建议加外部文件锁(如
)
即使追加安全,也要注意日志行完整性:避免一个
写半行就被打断,应尽量用单次
或
输出完整逻辑行
追加写入看似简单,真正容易翻车的是对
模式底层语义的理解偏差,以及跨平台、跨进程场景下的隐含假设。
std::ios::appstd::ofstreamstd::ios::appseekp()std::ios::appstd::ios::outstd::ios::appstd::ios::outappstd::ios::inappstd::ios::ateseekp(0, std::ios::end)appateseekp()std::ios::atewrite()<<appseekp(0, std::ios::end)appO_APPENDateseekpstd::ofstreamopen()std::ofstream file("log.txt", std::ios::app); // ✅ 正确:只追加
std::ofstream file("log.txt", std::ios::out | std::ios::app); // ✅ 等价,但冗余
std::ofstream file("log.txt"); // ❌ 默认是 out,会清空文件!
std::ios::truncapptruncfile.imbue(std::locale("")); std::locale::global(std::locale(""))file.flush()std::ios::appoperator<<ofstreamappO_APPENDwrite()O_APPENDLockFileEx<<<<write()app