应使用 _wfopen 而非 fopen 处理宽字符文件:它接受 wchar_t* 路径和模式(如 L"wt, ccs=UTF-16LE"),支持 BOM 与编码协商;std::wofstream 需手动写入 \xFF\xFE BOM 才能正确显示中文。
用
打开宽字符文件会直接失败
Windows 上用
写入
数据,文件内容大概率是乱码或空——因为
默认按窄字符(
)处理,不识别 BOM,也不做 UTF-16 编码转换。
真正能安全读写宽字符的,是 Microsoft 提供的宽字符版 C 标准库函数:
(注意开头下划线和 w 前缀),它接受
路径和模式,并在内部处理编码协商。
在 Windows 下支持
这类编码标识,Linux/macOS 不支持,别跨平台硬搬
路径必须是
,不能传
,否则崩溃或静默失败
模式字符串也得是宽字符串,比如
,漏掉
前缀是常见低级错误
默认不写 BOM,中文全变方块
用
直接 L"你好",生成的文件在记事本里打开大概率显示为“??”,因为流默认以本地宽字符编码(通常是 UTF-16 但无 BOM)写入,而 Windows 记事本只靠 BOM 判断是否 UTF-16。
必须手动写入 BOM 并设置流的 locale,否则编码不可靠:
立即学习
“
C++免费学习笔记(深入)
”;
C知道
CSDN推出的一款AI技术问答工具
下载
先用
绑定系统 locale(仅 Windows 有效)
再对流调用
,例如
(Windows codepage 1200 = UTF-16LE)
最稳妥方式:用
禁用缓冲后,先写
(UTF-16LE BOM),再
跨平台读宽字符文件,
在 Linux 下基本失效
Linux 的 libc 对宽字符文件流支持极弱:
读 UTF-8 文件会把每个字节当一个
,结果全是错码;读 UTF-16 更是直接失败——因为 glibc 的
已被弃用,且无默认 UTF-16 支持。
实际可行方案只有两个:
统一用
按
读原始字节,自己检测 BOM(
/
/
),再用
或第三方库(如 ICU、utf8cpp)转成
彻底放弃
,改用
+
+ 手动 UTF-16 解码,控制权更稳
别依赖
:C++17 已标为 deprecated,GCC/Clang 新版本编译直接报错
写入时用
比
更干净
如果只是写纯文本(不含格式化),
是比
更轻量、更少坑的选择——它不解析格式符,不会因漏传参数导致未定义行为,也不会把
当指令误处理。
安全;
会崩
自动在末尾加换行?不会。它严格输出传入的
,换行得自己加
返回值是
,成功时返回非负值,失败返回
,务必检查,尤其写网络文件系统或权限受限路径时
BOM 的位置、locale 的绑定时机、跨平台时 wchar_t 的语义漂移——这些不是边缘情况,而是宽字符 IO 的主干障碍。绕不开,只能一个个对齐。
fopenfopen("中文.txt", "w")wchar_tfopenchar_wfopenconst wchar_t*_wfopen"wt, ccs=UTF-16LE"wchar_t[]std::string.c_str()L"wt, ccs=UTF-16LE"Lstd::wofstreamstd::wofstreamstd::locale::global(std::locale(""))imbue()out.imbue(std::locale(".1200"))out.rdbuf()->pubsetbuf(nullptr, 0)\xFF\xFEstd::wifstreamstd::wifstreamwchar_tcodecvtstd::ifstreamstd::vector\xFF\xFE\xFE\xFF\xEF\xBB\xBFstd::mbstowcsstd::wstringwchar_tstd::u16stringstd::ifstreamstd::codecvt_utf8_utf16fputwsfwprintffputwsfwprintf%fputws(L"路径含%符号.txt", fp)fwprintf(fp, L"路径含%符号.txt")fputwswchar_t*L"\n"intEOF