c++如何读取和解析带BOM头的UTF-8与UTF-16文本流【详解】

张开发
2026/6/7 7:12:39 15 分钟阅读
c++如何读取和解析带BOM头的UTF-8与UTF-16文本流【详解】
根本原因是 std::ifstream 默认按字节流打开不识别 BOM将 UTF-8 或 UTF-16 BOM 当普通字符读入导致解析失败需二进制模式打开、手动检测并跳过 BOM再转码处理。读取时直接遇到乱码或空内容根本原因是 C 标准库的 std::ifstream 默认按字节流打开不识别 BOM遇到 UTF-8 BOM0xEF 0xBB 0xBF或 UTF-16 BOM0xFF 0xFE 或 0xFE 0xFF时会把它们当普通字符读入导致后续解析失败——比如 std::getline 读出首行含不可见字节JSON 解析器直接报 invalid character。实操建议立即学习“C免费学习笔记深入”用二进制模式打开文件std::ifstream f(file.txt, std::ios::binary)避免系统层面对换行符或编码的隐式转换手动读前 3 字节判断 UTF-8 BOM前 2 字节判断 UTF-16 BOM别依赖 std::codecvt_utf8已弃用或平台 API 做自动探测UTF-16 小端和大端 BOM 必须区分读到 0xFF 0xFE 是 UTF-16LE0xFE 0xFF 是 UTF-16BE混用会导致每两个字节被颠倒解析std::wifstream 读 UTF-16 文件却只读出一半字符这是最典型的坑Windows 下 std::wifstream 默认用本地宽字符编码通常是 UTF-16LE但若没显式指定 locale它不会跳过 BOM也不会按 UTF-16 单位解析——而是把每个字节当一个 wchar_t 处理结果一个汉字变成两个乱码宽字符。实操建议立即学习“C免费学习笔记深入”必须在打开前设置 localef.imbue(std::locale(f.getloc(), new std::codecvt_utf16char16_t std::little_endian));/char16_t改用 char16_t 流而非 wchar_t 流避免 Windows 上 wchar_t 是 16 位但语义模糊的问题更稳妥的做法是先用 std::ifstream 读原始字节检测 BOM 后用 std::mbrtoc16 或 std::from_bytesC20转成 std::u16string跨平台读 UTF-8 文件时 BOM 导致 std::stoi 失败Linux/macOS 下很多工具生成的 UTF-8 文件带 BOM而 std::stoi、std::stod 等函数遇到开头的 0xEF 0xBB 0xBF 会立即返回 0 并设 failbit不是抛异常容易被忽略。 文小言 百度旗下新搜索智能助手有问题问小言。

更多文章