c++怎么处理BOM头文件_跳过UTF-8签名EF BB BF【详解】

畫卷琴夢

畫卷琴夢

2026-03-19

807人浏览

原创

c++oding="utf-8" ?>

读文件前需用二进制模式打开,读取前3字节判断是否为0xef 0xbb 0xbf,若是则seekg(3)跳过,否则回退到开头;不可依赖wifstream或c库自动处理bom。

c++怎么处理bom头文件_跳过utf-8签名ef bb bf【详解】

读文件前怎么检测并跳过 UTF-8 BOM

Windows 上用记事本或某些编辑器保存的 UTF-8 文件,开头可能带 EF BB BF 这三个字节——它不是内容,只是编码标记。C++ 标准库不自动识别或跳过它,直接读会导致 std::string 开头多出乱码,std::getline 解析 JSON、CSV 或配置时可能直接失败。

实操上,得自己检查文件头:

  • std::ifstreamstd::ios::binary 模式打开,避免文本模式自动换行转换干扰字节判断
  • 读前 3 字节,比对是否等于 0xEF, 0xBB, 0xBF
  • 若匹配,再调用 file.seekg(3) 跳过,后续读取就从真实内容开始

示例片段:

std::ifstream file("data.txt", std::ios::binary);
if (!file.is_open()) return;
std::array<char> bom{};
file.read(bom.data(), 3);
if (bom == std::array<char>{'\xEF', '\xBB', '\xBF'}) {
    file.seekg(3); // 跳过 BOM
} else {
    file.seekg(0); // 回到开头,没 BOM 就正常读
}
</char></char>

std::wifstream 读 UTF-8 带 BOM 会怎样

很多人想省事,直接用宽字符流读 UTF-8 文件,但这是错的:std::wifstream 默认按本地多字节编码(如 GBK)解码,不是 UTF-8;即使手动设 imbue,标准库也**不保证支持 UTF-8 BOM 自动剥离**,不同编译器行为不一致(MSVC 可能吞掉 BOM,GCC/Clang 常原样当宽字符读,导致第一个 wchar_t 变成 0xFFFD 或乱码)。

结论很直接:别用 std::wifstream 处理 UTF-8 文件,尤其要兼容 Windows 编辑器生成的带 BOM 文件。

C函数速查手册(CHM版)
C函数速查手册(CHM版)

C函数速查手册(CHM版)

下载
  • 真正需要宽字符处理,先用二进制方式读、手动跳 BOM,再用 std::from_bytes(C++20)或第三方库(如 ICU、utf8cpp)转码
  • 纯 ASCII 或已知无 BOM 的 UTF-8,可放心用 std::ifstream + std::string

跨平台读取时 BOM 处理的兼容性坑

Linux/macOS 下多数工具(vimgccpython3)默认不加 BOM,但 Windows 记事本、VS、某些 GUI 配置编辑器会加——这意味着你本地测试没问题,一到客户环境就崩。

关键点在于:BOM 是可选的,不是 UTF-8 标准强制要求。所以不能假设“有 BOM 才是 UTF-8”,也不能假设“没 BOM 就不是 UTF-8”。

  • 生产代码里,只要文件来源不可控(比如用户上传、跨平台配置共享),就必须做 BOM 检测,不能只靠文档约定
  • 检测逻辑必须放在最开头,且只检测一次——重复 seekg 或多次读头 3 字节容易破坏流状态
  • 注意 std::ifstream::peek() 在某些老版本 libstdc++ 上对二进制流行为异常,优先用 read() + gcount() 判断是否真读到了 3 字节

fopen + fread 怎么安全跳 BOM

C 风格 IO 在嵌入式或性能敏感场景仍常见,处理 BOM 同样要主动干预。核心问题一样:fopen("xxx.txt", "r") 在 Windows 下可能被当作 ANSI 打开,fread 读出的 EF BB BF 会被误解释为三个独立字符。

正确做法是强制二进制模式,并手动比对:

  • fopen("xxx.txt", "rb") 打开
  • fread(buf, 1, 3, fp) 读 3 字节,检查 buf[0]==0xEF && buf[1]==0xBB && buf[2]==0xBF
  • 若匹配,调用 fseek(fp, 3, SEEK_SET);否则 fseek(fp, 0, SEEK_SET)
  • 之后所有读取(fgetsfread)都从正确位置开始

注意:不要用 "r" 模式配合 setlocale(LC_ALL, "en_US.UTF-8") 试图让 C 库处理 BOM——POSIX 不要求 C 库识别 UTF-8 BOM,glibc 实际也不处理。

BOM 处理看似只是三字节的事,但一旦漏掉,错误会藏在数据解析深层,比如 JSON 解析器报“unexpected token”,而真正原因只是第一行开头多了个不可见的 EF BB BF。最稳妥的方式,就是在任何外部输入的文本文件打开后、正式解析前,插一段固定检测逻辑——写一次,到处安心。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

2023.08.07

1563

5

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.23

1426

1

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

2023.10.13

589

3

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

2025.09.10

1337

7

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.02

2958

3

fgets在c语言中的用法
fgets在c语言中的用法

本专题整合了c语言中fgets用法介绍,阅读专题下面的文章了解更多详细内容。

2025.08.27

51

4

登录token无效
登录token无效

登录token无效解决方法:1、检查token的有效期限,如果token已经过期,需要重新获取一个新的token;2、检查token的签名,如果签名不正确,需要重新获取一个新的token;3、检查密钥的正确性,如果密钥不正确,需要重新获取一个新的token;4、使用HTTPS协议传输token,建议使用HTTPS协议进行传输 ;5、使用双因素认证,双因素认证可以提高账户的安全性。

2023.09.14

7778

6

登录token无效怎么办
登录token无效怎么办

登录token无效的解决办法有检查Token是否过期、检查Token是否正确、检查Token是否被篡改、检查Token是否与用户匹配、清除缓存或Cookie、检查网络连接和服务器状态、重新登录或请求新的Token、联系技术支持或开发人员等。本专题为大家提供token相关的文章、下载、课程内容,供大家免费下载体验。

2023.09.14

1077

5

token怎么获取
token怎么获取

获取token值的方法:1、小程序调用“wx.login()”获取 临时登录凭证code,并回传到开发者服务器;2、开发者服务器以code换取,用户唯一标识openid和会话密钥“session_key”。想了解更详细的内容,可以阅读本专题下面的文章。

2023.12.21

2025

3

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
RabbitMQ 教程手册
RabbitMQ 教程手册

共0课时 | 0人学习

Linux man-pages 项目
Linux man-pages 项目

共0课时 | 0人学习

C# 教程
C# 教程

共94课时 | 20.2万人学习