应使用二进制模式写入UTF-8编码的JSON字符串:以std::ios::binary打开文件,用write()写入原始字节流,避免文本模式下的编码转换与转义干扰。

JSON字符串写入文件时中文乱码或转义错误
直接用 std::ofstream 写入含中文或特殊字符的 JSON 字符串,大概率出现乱码、双引号消失、反斜杠被吃掉——根本原因不是 JSON 本身有问题,而是 ofstream 默认按系统本地编码(如 GBK)写入,而 JSON 字符串通常是 UTF-8 编码,且内部已包含转义(如 "\u4f60" 或 "\"")。
实操建议:
- 确认你的 JSON 字符串确实是合法 UTF-8 编码(比如来自
nlohmann::json::dump()或rapidjson::StringBuffer输出) - 不要手动对字符串再做一次
std::string层面的转义(例如把"替换成"),JSON 库输出的字符串已经是可直接写入的原始字节流 - Windows 下需显式设置文件流为 UTF-8 模式:调用
myfile.imbue(std::locale("", std::locale::ctype))不可靠;更稳妥的是用_setmode(_fileno(stdout), _O_U16TEXT)类思路不适用文件流——干脆绕过,改用二进制模式写入
用 std::ofstream 以二进制模式保存 JSON 字符串
这是最简单、兼容性最好的做法:跳过所有文本编码转换逻辑,把 JSON 字符串当纯字节序列写进去。UTF-8 本身就是字节安全的,只要字符串内容没错,文件就没错。
实操建议:
- 打开文件时加
std::ios::binary标志:std::ofstream file("data.json", std::ios::out | std::ios::binary) - 写入时用
file.write(str.data(), str.size()),别用流插入操作符(它会触发格式化和换行处理) - 确保
str是std::string(而非std::wstring),且内容为 UTF-8 字节 - 写完记得
file.close()或让对象析构,避免缓冲区未刷新
示例片段:
std::string json_str = R"({"name":"张三","score":95.5})";
std::ofstream f("output.json", std::ios::out | std::ios::binary);
if (f.is_open()) {
f.write(json_str.data(), json_str.size());
f.close();
}
JSON 库输出与手动拼接字符串的转义差异
很多人试图自己用 std::string 拼接 JSON,比如 "{"name":"" + name + ""}",这极易出错:漏转义引号、斜杠、控制字符,或重复转义(如把 "
" 变成 "\n")。而正规 JSON 库(如 nlohmann::json)的 dump() 方法会严格按 RFC 8259 处理所有字符。
实操建议:
- 永远优先用 JSON 库生成字符串,而不是手写或正则替换
-
nlohmann::json::dump()默认不缩进、不转义非 ASCII 字符(即保留中文原文),若需 Unicode 转义("\u4f60"),传参json.dump(-1, ' ', false, nlohmann::json::error_handler_t::strict)不起作用;正确方式是设json.dump(0, ' ', true)—— 第三个参数为true表示escape_unicode - 如果用
rapidjson,StringBuffer+Writer默认输出 UTF-8 原始字节,无需额外处理
跨平台文件路径与权限问题(尤其 Windows)
写 JSON 文件失败,有时根本不是编码问题,而是路径非法或无写入权限。比如在 Windows 上尝试写入 C:config.json(需要管理员权限),或路径含 *? 等非法字符。
实操建议:
- 路径用正斜杠
/或双反斜杠\,避免单个被当转义(如"C: empdata.json"中的会被解释为制表符) - 写入前检查目录是否存在:
std::filesystem::create_directories()(C++17)比手动mkdir更可靠 - 打开文件后务必检查
file.is_open(),否则write()会静默失败 - Linux/macOS 下注意目标目录是否只读,或磁盘满;Windows 下注意杀毒软件可能临时锁定文件
写文件这件事,真正卡住人的往往不是 JSON 格式本身,而是“以为字符串能直接塞进去”和“没意识到流对象在后台偷偷做了编码转换”。二进制模式写入+库生成字符串,是最少意外的组合。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











