UTF-32 和 UTF-16 的一个 Code Unit,需要转换成多个字节的序列,因此存在字节序的问题。
可以在 UTF-32 或 UTF-16 编码的字节流开头,添加字节顺序标记 (byte-order mark, BOM),来标识字节序。
BOM 是 U+FEFF
字符的名称。编码时,将 U+FEFF
编码在字节流的开头。解码时,读取前几个字节,就知道编码时的字节序了。
例如 UTF-16 的大端序,U+FEFF
会被编码成 0xFEFF
,而小端序则会编码成 0xFFFE
。这样根据开头是 0xFEFF
还是 0xFFFE
,就知道编码时使用的大端序还是小端序了。
同理 UTF-32 的大端序,U+FEFF
会被编码成 0x00 00 FE FF
,而小端序则会编码成 0xFF FE 00 00
。这样根据开头,不光能区分出字节序,还能区分出是 UTF-32 还是 UTF-16。
UTF-8 的一个 Code Unit 只需要转换为 1 个字节,因此不存在字节序的问题,也就不需要 BOM。而且 0xFEFF
或 0xFFFE
字节序列,在 UTF-8 中都是不可能出现的。所以根据 BOM,也能区分出编码方式是不是 UTF-8。
如果硬要给 UTF-8 加 BOM,那就是将 0xFEFF
(0b1111 1110 1111 1111
) 进行 UTF-8 编码,得到 0xEF BB BF
(0b1110 1111 1011 1011 1011 1111
),放在字节流的最前面。
之所以使用 U+FEFF
这个字符来标识字节序,可能是因为这个字符本身就表示“零宽非断空格”的含义。把他放在最前面,解码的时候支持 BOM,就把他按照字节序去理解;不支持的就把他解析成一个“零宽非断空格”,展示起来也没有任何影响。当然这是我瞎猜的,而且从 Unicode 3.2 开始,U+FEFF
已经专门用来标记字节序,没有其他含义了。
【字节顺序标记】相关文章:
- 字节序
- 详解字符编码与 Unicode