为什么我们必须在UTF-16和UTF-32编码的情况下指定BOM

时间:2016-01-20 17:57:45

标签: unicode encoding utf-8 utf-16 byte-order-mark

我不太了解UTF编码和BOM背后的原理。

如果计算机已经知道如何将多字节数据类型(例如,大小为4字节的整数)组合成一个变量,那么在UTF-16和UTF-32中使用BOM有什么意义呢?为什么我们需要为这些编码明确指定它呢?

为什么我们不需要为UTF-8指定它? Unicode标准表示它是“面向字节的”,但即便如此,我们还需要知道它是否是编码代码点的第一个字节。或者它是否在每个字符的前/后位中指定?

3 个答案:

答案 0 :(得分:2)

UTF-16是两个字节宽,让我们调用字节B0|B1。 假设我们有字母'a',这在逻辑上是0x0061。不幸的是,不同的计算机体系结构以不同的方式将这个数字存储在内存中,在x86平台上,首先存储较低有效字节(在较低的内存地址处),因此'a'将存储为00|61。在PowerPC上,它将存储为61|00,因此这两种架构称为小端和大端。

为了加速字符串处理库,通常以本机顺序存储两个字节字符(大结尾或小结尾)。交换字节太贵了。

现在假设PowerPC上的某个人将字符串写入文件,库将写入字节00|61,现在x86上的某些人想要读取这些字节,但这是否意味着00|61或{{1} }?我们可以在字符串的开头放置特殊序列,这样任何人都会知道用于保存字符串的字节顺序,并正确处理它(在字节序之间转换字符串是一项代价高昂的操作,但大多数情况下x86字符串将在x86 arch上读取,和PowerPC机器上的PowerPC字符串)

使用UTF-8这是不同的故事,UTF-8使用单一顺序并将字符长度编码为第一个字符的第一位模式。 UTF-8编码在Wikipedia上有详细描述。一般来说,它是设计以避免endian'ess的问题

答案 1 :(得分:1)

不同的架构可以对事物进行不同的编码。一个系统可能将0x12345678写为0x12 0x34 0x56 0x78,另一个系统可能将其写为0x78 0x56 0x34 0x12。了解源系统如何编写内容非常重要。字节是读取或写入的最小单位,因此如果格式是逐字节写入的,则没有问题,就像没有系统在读取另一个写入的ASCII文件时一样。

UTF-16 BOM,U+FEFF将写为0xFE 0xFF或0xFF 0xFE,具体取决于系统。知道这些字节的写入顺序告诉读者字节将用于文件其余部分的顺序。 UTF-32使用相同的BOM字符,填充16个零位,但其使用方法相同。

另一方面,UTF-8被设计为一次读取一个字节。因此,即使在处理多字节字符时,所有系统的顺序都是相同的。

答案 2 :(得分:1)

UTF-16和UTF-32编码不指定字节顺序。在8位字节流中,代码点U + FEFF可以用UTF-16编码为字节FE,FF(大端)或FF,FE(小端)。流编写器显然无法知道流将在哪里结束(文件,网络套接字,本地程序?),因此您在开头放置BOM以帮助读者确定编码和字节顺序变体。 / p>

UTF-8没有这种歧义,因为它从一开始就是面向字节的编码。在UTF-8中编码此代码点的唯一方法是以精确的顺​​序使用字节EF,BB,BF。 (方便的是,序列化的第一个字节中的高位也会显示序列占用的字节数。)