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

如何使用C++ ifstream读取文件中的空终止UTF-8和UTF-16字符串

现有代码的问题

你当前的实现思路方向是正确的,但存在几个明显缺陷:

  • 未处理字节序问题:直接读取2字节赋值给char16_t的逻辑默认了文件存储的UTF-16字节序和当前主机的字节序完全一致,如果文件是UTF-16 LE而主机是大端,或者反过来,读出来的字符会完全乱码。
  • 未判断流读取状态:没有检查binary.read()的返回结果,如果文件读取到末尾还没有遇到0x0000终止符,会读取无效内存值,触发未定义行为。
  • 使用已弃用接口:std::wstring_convert和std::codecvt_utf8_utf16从C++17开始已经被标准库弃用,在高版本编译器下会报警告,且后续标准可能移除该接口。
  • 灵活性不足:函数直接将UTF-16转成UTF-8返回,如果业务需要保留原std::u16string格式还需要额外修改。

正确的UTF-16字符串读取实现

读取UTF-16字符串的核心逻辑确实是按2字节为单位读取,直到遇到0x0000终止符,只需要补充字节序处理、异常判断即可,优化后的可参考实现如下:

#include <fstream>
#include <string>
#include <cstdint>

// 辅助函数:将小端存储的2字节转为主机字节序,文件是大端的话替换为对应的be16_to_host即可
inline char16_t le16_to_host(const char* bytes) {
    return static_cast<char16_t>(
        (static_cast<uint8_t>(bytes[0])) | 
        (static_cast<uint8_t>(bytes[1]) << 8)
    );
}

// 读取原始UTF-16字符串
std::u16string binaryReader::read_u16str() {
    std::u16string result;
    char buf[2];
    // 提前分配容量避免多次扩容,可根据实际场景调整预分配大小
    result.reserve(64);
    while (binary.read(buf, 2)) {
        char16_t ch = le16_to_host(buf);
        if (ch == u'\0') {
            break;
        }
        result.push_back(ch);
    }
    return result;
}

// 轻量UTF-16转UTF-8实现(仅支持BMP平面字符,需支持代理对可自行扩展逻辑)
std::string u16_to_u8(const std::u16string& u16_str) {
    std::string u8_str;
    u8_str.reserve(u16_str.size() * 3);
    for (char16_t ch : u16_str) {
        if (ch <= 0x7F) {
            u8_str += static_cast<char>(ch);
        } else if (ch <= 0x7FF) {
            u8_str += static_cast<char>(0xC0 | (ch >> 6));
            u8_str += static_cast<char>(0x80 | (ch & 0x3F));
        } else {
            u8_str += static_cast<char>(0xE0 | (ch >> 12));
            u8_str += static_cast<char>(0x80 | ((ch >> 6) & 0x3F));
            u8_str += static_cast<char>(0x80 | (ch & 0x3F));
        }
    }
    return u8_str;
}

额外注意:如果文件携带BOM,可先读取前2字节判断字节序,再动态选择对应的字节序转换函数即可。

内容的提问来源于stack exchange,提问作者file-tracer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 01:54:03