std::ofstream默认以文本模式打开文件,自动处理平台换行符;若需写入二进制数据,必须显式指定std::ios::binary标志,否则Windows下 会被转为 导致数据错误。

用 std::ofstream 打开文件并写入字符串最直接
默认以文本模式打开,写入内容会自动按平台换行符处理(Windows 用
,Linux/macOS 用
)。注意:如果文件不存在会自动创建;如果已存在,默认会清空原有内容再写入。
常见错误是忘记检查文件是否成功打开:
-
std::ofstream构造后立即用.is_open()或隐式转换为bool判断,比如if (!fout) { /* 失败 */ } - 路径中反斜杠要写成
\或用正斜杠/,否则"C:dataout.txt"里的d和o会被当转义字符解析 - 中文路径或含中文内容时,Windows 下需用
std::locale绑定支持 UTF-8 的 facet,否则可能乱码(VS2015+ 默认窄字符流不支持 UTF-8 BOM)
写入二进制数据必须加 std::ios::binary 标志
不加这个标志时,
在 Windows 下会被悄悄转成
,导致读回的字节长度和原始不符——这对图片、序列化结构体、加密数据等场景是致命问题。
实操要点:
立即学习“C++免费学习笔记(深入)”;
- 打开时写成
std::ofstream fout("data.bin", std::ios::binary); - 写原生内存用
.write(reinterpret_cast<const char>(&x), sizeof(x))</const>,不能直接传&x给操作符 - 结构体含指针或虚函数时不能直接
write整块内存,需手动序列化字段
追加写入要显式指定 std::ios::app
只用 std::ios::app 就够了,不用再加 std::ios::out(它会被自动包含)。关键行为是:每次写操作前,文件指针自动跳到末尾,且**无视你之前调用的 .seekp()**。
容易踩的坑:
- 误以为
std::ios::app | std::ios::binary能追加二进制——可以,但依然受“强制定位到末尾”约束,无法在中间插入 - 多线程同时追加写同一文件,C++ 标准不保证原子性,可能产生交错数据,需外加互斥或改用单写入器
- 用
std::ios::ate是打开即定位到末尾,但后续写仍从当前位置开始,不会自动跳转,和app有本质区别
写完必须 .close() 或依赖析构,否则缓冲区可能没刷出
流对象离开作用域会自动析构并调用 close(),所以局部变量通常没问题。但以下情况必须手动干预:
- 写入大文件中途想确认数据已落盘,调
.flush()强制刷缓冲区(注意:不等于写入磁盘,只是交给 OS) - 需要复用同一个
std::ofstream对象写多个文件,必须先.close()再.open(),否则open()失败且failbit被置位 - 捕获异常前未
close(),而析构又因异常跳过——RAII 机制仍会执行析构,但某些旧编译器或自定义 streambuf 可能有例外
真正容易被忽略的是:用 std::endl 代替 "
" 会额外触发 flush(),高频写小数据时显著拖慢性能,除非真需要立即可见,否则优先用 "
"。


















