[原创](Modern C++)现代C++的关键性概念: 文件编码细节之一:BOM(Byte Order Mark, 字节顺序标记)
常用网名: 猪头三
出生日期: 1981.XX.XX
企鹅交流: 643439947
个人网站: 80x86汇编小站
编程生涯: 2001年~至今[共24年]
职业生涯: 22年
开发语言: C/C++、80x86ASM、PHP、Perl、Objective-C、Object Pascal、C#、Python
开发工具: Visual Studio、Delphi、XCode、Eclipse、C++ Builder
技能种类: 逆向 驱动 磁盘 文件
研发领域: Windows应用软件安全/Windows系统内核安全/Windows系统磁盘数据安全/macOS应用软件安全
项目经历: 磁盘性能优化/文件系统数据恢复/文件信息采集/敏感文件监测跟踪/网络安全检测
[序言]
在现代软件开发中, 文本文件的编码问题至关重要, 尤其是在不同平台、不同工具之间传输和处理文本文件时, 编码格式的不一致可能会导致乱码甚至解析错误. Unicode作为一种通用字符集, 为跨语言和跨平台的文本存储提供了解决方案, 其中BOM(Byte Order Mark, 字节顺序标记)是一个关键性的编码概念.
[BOM作用]
BOM(Byte Order Mark)是Unicode编码中的一个特殊字节序列, 主要作用如下:
1> 指明文件的编码格式
BOM可以用于指示文本文件使用的编码格式, 例如UTF-8、UTF-16(LE/BE)、UTF-32(LE/BE).
2> 区分字节序(大小端)
在UTF-16和UTF-32编码中, 字符由两个或多个字节组成, 不同系统可能采用不同的字节存储顺序(大端BE 或 小端LE), BOM可用于标识文件的字节序, 避免解析错误.
3> 兼容性问题
理论上UTF-8不需要BOM, 因为UTF-8以单字节方式存储ASCII兼容字符. 但某些Windows文字编辑器(如Notepad)会自动添加BOM(EF BB BF)作为标识, 以便区分UTF-8编码和ANSI
4> 防止误判编码格式
在没有BOM的情况下, 某些软件可能会误判文件的编码格式.
[常见BOM标记]
编码格式 BOM 字节序列(十六进制) 字节长度
UTF-8 EF BB BF 3 字节
UTF-16 LE FF FE 2 字节
UTF-16 BE FE FF 2 字节
UTF-32 LE FF FE 00 00 4 字节
UTF-32 BE 00 00 FE FF 4 字节
[ANSI格式的文件不需要BOM]
ANSI不是一种具体的编码, 而是Windows术语, 指"本地代码页编码", 不需要额外的BOM标识.
Windows 简体中文(GBK/CP936)
Windows 繁体中文(Big5/CP950)
Windows 西欧语言(ISO-8859-1/CP1252)
Windows 日文(Shift-JIS/CP932)
Windows 记事本里"ANSI"选项实际上是本地代码页, 也就是默认使用本地语言的代码页. 比如日文Windows系统, 默认就使用(Shift-JIS/CP932). ANSI仅适用于Windows本地环境, 不适用于跨平台开发, 因此在国际化应用中, 建议使用UTF-8(无 BOM).
[跨平台问题]
1> UTF-8文件通常不建议使用BOM
在跨平台开发中, 推荐使用不带BOM的UTF-8编码, 特别是用于存储源代码和配置文件.
2> UTF-8源代码文件避免BOM
C++源代码文件(UTF-8 编码)如果带BOM, 可能会导致某些编译器(如 GCC)解析错误.
3> Windows Visual Studio默认使用带BOM的UTF-8
在Windows开发环境(如Visual Studio 2022)中, 默认情况下, UTF-8源代码文件会包含BOM. 这可能导致代码在Linux或macOS上出现兼容性问题.
4> Linux处理Windows生成的UTF-8文件可能出错
在Linux或macOS处理带BOM的UTF-8文件时, 可能会因BOM被误识别为文本内容而导致解析错误.
5> 读取文本文件时, 可根据实际情况和需求, 检查并移除BOM
比如: 在编写C++代码时, 如果需要读取UTF-8文件, 应检查开头是否有BOM, 并在必要时移除它.
[BOM 标识可以被移除]
在某些情况下, 读取文本文件时BOM可能会被当作普通字符读取, 导致解析问题. 例如:
* 二进制文件处理
如果按二进制模式读取UTF-8、UTF-16 或 UTF-32文件, BOM也会被读取出来.
[总结]
在现代C++开发中, 正确理解和处理BOM能有效避免编码问题, 确保代码在不同平台上的兼容性和可读性. 因此, 在编写和读取文本文件时, 建议尽量使用 UTF-8(无 BOM)格式, 以确保最大程度的跨平台兼容性.