认识 BOM 头、以及 BOM 与 Unicode 的关系

警告
本文最后更新于 2023-06-15,文中内容可能已过时。

BOM 问题可是坑过不少人,一直备受吐槽。我是在实现Golang CSV 库时被 BOM 坑了一手,这次借着梳理编码与解码方面的知识,重新认识一下 BOM 这个玩意儿~

BOM 是 Byte Order Mark 的缩写,译为字节顺序标记。为什么需要标记字节顺序呢?这就要提到 Unicode 与 UTF16、UTF32 编码了:

以汉字严为例,Unicode 码是 4E25,使用 UTF16 编码需要两个字节存储,一个字节是4E,另一个字节是25。既然用两个字节表示一个字符,那么谁在前谁在后就成了一个问题:

  1. 4E在前,25在后,这种字节顺序叫做 Big endian,也叫大端字节序,简称大端序。
  2. 25在前,4E在后,这种字节顺序叫做 Little endian,也叫小端字节序,简称小端序。

正是为了标记大小端序,才有了 BOM 的诞生。

我个人觉得统一采用一种方式就好了啊😑。完全无法理解为什么要搞两种方式。

不过,还是尊重历史吧😂

BOM

BOM 是 Byte Order Mark 的缩写,译为字节顺序标记,是插入到 Unicode 文件开头的特殊标记,用来识别 Unicode 文件的编码类型和字节顺序。

对于 UTF-16,FEFF代表大端序,FFFE代表小端序。

对于 UTF-32,0000 FEFF 代表大端序,FFFE 0000代表小端序。

UTF8 BOM 头

上文提到了 UTF-16、UTF-32 存在 BOM 头,那 UTF-8 编码是否也有 BOM 头呢?

答案是,有,但不需要。

如果清楚 UTF-8 编码原理的话,大家会知道 UTF-8 完全不需要标记字节顺序,也就不需要 BOM 头!

但是不知道什么原因,UTF-8 也存在 BOM 头:EF BB BF

为什么 UTF8 的 BOM 头是 EF BB BF

为什么是EF BB BF呢?因为EF BB BF转换成二进制为:11101111 10111011 10111111,对应 UTF-8 的三字节编码模式:1110xxxx 10xxxxxx 10xxxxxx,进而我们能拿到原始数据:1111 1110 1111 1111,转换为 16 进制为 FEFF,对应上文的大端序。

如果不了解 UTF-8 编码,请看:https://rustyscript.com/zh-cn/posts/encode/unicode/

到底该不该用 BOM

BOM 是 Windows 搞出来的玩意,Linux 早期是不支持的,所以如果使用了 BOM,在跨平台时会出问题!

最佳实践

最佳实践应该是:使用 UTF-8 编码,且不用 BOM 头,它兼具了一些优点:

  1. 不存在乱码问题。
  2. 节省存储空间。
  3. 没有 BOM 头的坑。

更多与编码技术相关的博文:编码与解码 - 腐蚀脚本

转载声明:本文允许转载,原文链接:认识 BOM 头、以及 BOM 与 Unicode 的关系 - 腐蚀脚本


参考:

  1. https://juejin.cn/post/6884571798751412238
Buy me a coffee~
室长 支付宝支付宝
室长 微信微信
0%