You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

特定日文Unicode字符串引发C++文件读写异常的原因及解决

问题:wstring读写日文字符时部分字符串被截断

问题背景

长期使用以下C++代码读写包含日文字符的wstring,大部分场景正常运行超一年,但测试特定字符串时出现异常:写入「宴会」后读取仅获首字符,字符串被截断;测试「学校」则完全正常。

读写代码

#include <iostream>
#include <sstream>
#include <fstream>
using namespace std;

std::wstring readUnicodeFile(const char* filename)
{
    std::ifstream wif(filename);
    std::stringstream wss;
    wss << wif.rdbuf();
    std::string  const& str = wss.str();
    std::wstring wstr;
    wstr.resize(str.size() / sizeof(wchar_t));
    std::memcpy(&wstr[0], str.c_str(), str.size()); // copy data into wstring
    return wstr;
}

void writeUnicodetoFile(const char* myFile, wstring& ws)
{
    std::ofstream outFile(myFile, std::ios::out | std::ios::binary);
    outFile.write((char*)ws.c_str(), ws.length() * sizeof(wchar_t));
    outFile.close();
}

测试代码

int main() 
{
    wstring test1 = L"学校";  // Japanese word for school
    wstring test2 = L"宴会";  // Japanese word for banquet
    writeUnicodetoFile("somefilepath\\test.txt", test1);
    std::wstring s = readUnicodeFile("somefilepath\\test.txt");
}

异常原因

问题出在读取函数的文本模式打开文件:

  • 写入时用了std::ios::binary二进制模式,正确写入了wchar_t的原始字节(Windows下wchar_t为2字节UTF-16LE编码)。
  • 读取时std::ifstream wif(filename)默认是文本模式,该模式下会把字节0x1A(Windows系统的EOF控制字符)识别为文件结束标志,提前截断读取流。
  • 「宴会」的UTF-16编码为0x5B99 0x4F1A,对应字节序列是0x99 0x5B 0x1A 0x4F——其中0x1A触发了文本模式的截断逻辑,导致后续字节无法读取,最终只得到第一个字符。
  • 「学校」的UTF-16编码为0x5B66 0x6821,对应字节序列是0x66 0x5B 0x21 0x68,不包含文本模式的控制字符,所以读取正常。

修复方案

读取文件时同样使用二进制模式打开,避免文本模式对控制字符的解析:

修改readUnicodeFile函数的文件打开方式:

std::wstring readUnicodeFile(const char* filename)
{
    // 关键:添加std::ios::binary二进制模式
    std::ifstream wif(filename, std::ios::binary);
    std::stringstream wss;
    wss << wif.rdbuf();
    std::string  const& str = wss.str();
    std::wstring wstr;
    wstr.resize(str.size() / sizeof(wchar_t));
    std::memcpy(&wstr[0], str.c_str(), str.size());
    return wstr;
}

额外优化建议

  1. 添加错误处理:检查wif.is_open()或outFile.is_open()的返回值,避免文件打开失败时的静默错误。
  2. 跨平台兼容:Windows下wchar_t是UTF-16,Linux/macOS下是UTF-32,若需跨平台运行,建议统一使用UTF-8编码读写,避免依赖wchar_t的平台差异。

内容的提问来源于stack exchange,提问作者Alex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 11:15:38