跳转到主内容
websoft网络软件专家 - 深耕网络技术,打造实用软件!

c++ wide char读写文件方法 c++如何处理宽字符文件IO

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

相关文章