为什么我们必须在 UTF-16 和 UTF-32 编码的情况下指定 BOM
Why do we have to specify BOM in case of UTF-16 and UTF-32 encodings
不太明白UTF编码和BOM的原理
如果计算机已经知道如何将多字节数据类型(例如,大小为 4 字节的整数)组合到一个变量中,那么在 UTF-16 和 UTF-32 中使用 BOM 有什么意义?为什么我们需要为这些编码明确指定它?
为什么我们不需要为 UTF-8 指定它? Unicode 标准说它是 "byte oriented" 但即使这样我们也需要知道它是否是编码代码点的第一个字节。还是在每个字符的第一位/最后一位指定?
不同的体系结构可以对事物进行不同的编码。一个系统可能将 0x12345678 写为 0x12 0x34 0x56 0x78,而另一个系统可能将其写为 0x78 0x56 0x34 0x12。了解源系统如何编写内容的方法很重要。字节是读取或写入的最小单位,因此如果写入一种格式 byte-by-byte,没有问题,就像没有系统读取另一个写入的 ASCII 文件有问题一样。
UTF-16 BOM,U+FEFF
将写为 0xFE 0xFF 或 0xFF 0xFE,具体取决于系统。知道这些字节的写入顺序可以告诉 reader 文件其余部分的字节顺序。 UTF-32使用相同的BOM字符,填充16位零位,但用法相同
另一方面,UTF-8 被设计为一次读取一个字节。因此,所有系统上的顺序都是相同的,即使在处理 mutli-byte 个字符时也是如此。
UTF-16 是两个字节宽,我们称其为字节 B0|B1
。
假设我们有字母 'a' 这在逻辑上是数字 0x0061。不幸的是,不同的计算机体系结构在内存中以不同的方式存储此数字,在 x86 平台上,首先存储较低有效字节(在较低的内存地址),因此 'a' 将存储为 00|61
。在 PowerPC 上,这将存储为 61|00
,因此这两种架构被称为小端和大端。
为了加快字符串处理速度,库通常以本机顺序(大端或小端)存储两个字节的字符。交换字节太昂贵了。
现在假设有人在 PowerPC 上将字符串写入文件,库将写入字节 00|61
,现在有人在 x86 上想要读取这个字节,但这意味着 00|61
还是 61|00
?我们可以在字符串的开头放置特殊序列,以便任何人都知道用于保存字符串的字节顺序,并正确处理它(在字节序之间转换字符串是一项代价高昂的操作,但大多数时候 x86 字符串将在 x86 arch 上读取,和 PowerPC 机器上的 PowerPC 字符串)
对于 UTF-8,这是不同的故事,UTF-8 使用单顺序并将字符长度编码为第一个字符的第一位的模式。 UTF-8 编码在 Wikipedia 上有很好的描述。一般来说,设计是为了避免 endian'ess
问题
UTF-16 和 UTF-32 编码不指定字节顺序。在 8 位字节流中,代码点 U+FEFF 可以用 UTF-16 编码为字节 FE, FF(大端)或 FF, FE(小端)。流编写器显然不知道流将在哪里结束(一个文件、一个网络套接字、一个本地程序?)所以你在开头放一个 BOM 来帮助 reader(s) 确定编码和 byte-order变体。
UTF-8 没有这种歧义,因为它从一开始就是一种 byte-oriented 编码。在 UTF-8 中编码此代码点的唯一方法是按此精确顺序使用字节 EF、BB、BF。 (方便的是,序列化的第一个字节的高位也揭示了序列将占用多少字节。)
不太明白UTF编码和BOM的原理
如果计算机已经知道如何将多字节数据类型(例如,大小为 4 字节的整数)组合到一个变量中,那么在 UTF-16 和 UTF-32 中使用 BOM 有什么意义?为什么我们需要为这些编码明确指定它?
为什么我们不需要为 UTF-8 指定它? Unicode 标准说它是 "byte oriented" 但即使这样我们也需要知道它是否是编码代码点的第一个字节。还是在每个字符的第一位/最后一位指定?
不同的体系结构可以对事物进行不同的编码。一个系统可能将 0x12345678 写为 0x12 0x34 0x56 0x78,而另一个系统可能将其写为 0x78 0x56 0x34 0x12。了解源系统如何编写内容的方法很重要。字节是读取或写入的最小单位,因此如果写入一种格式 byte-by-byte,没有问题,就像没有系统读取另一个写入的 ASCII 文件有问题一样。
UTF-16 BOM,U+FEFF
将写为 0xFE 0xFF 或 0xFF 0xFE,具体取决于系统。知道这些字节的写入顺序可以告诉 reader 文件其余部分的字节顺序。 UTF-32使用相同的BOM字符,填充16位零位,但用法相同
另一方面,UTF-8 被设计为一次读取一个字节。因此,所有系统上的顺序都是相同的,即使在处理 mutli-byte 个字符时也是如此。
UTF-16 是两个字节宽,我们称其为字节 B0|B1
。
假设我们有字母 'a' 这在逻辑上是数字 0x0061。不幸的是,不同的计算机体系结构在内存中以不同的方式存储此数字,在 x86 平台上,首先存储较低有效字节(在较低的内存地址),因此 'a' 将存储为 00|61
。在 PowerPC 上,这将存储为 61|00
,因此这两种架构被称为小端和大端。
为了加快字符串处理速度,库通常以本机顺序(大端或小端)存储两个字节的字符。交换字节太昂贵了。
现在假设有人在 PowerPC 上将字符串写入文件,库将写入字节 00|61
,现在有人在 x86 上想要读取这个字节,但这意味着 00|61
还是 61|00
?我们可以在字符串的开头放置特殊序列,以便任何人都知道用于保存字符串的字节顺序,并正确处理它(在字节序之间转换字符串是一项代价高昂的操作,但大多数时候 x86 字符串将在 x86 arch 上读取,和 PowerPC 机器上的 PowerPC 字符串)
对于 UTF-8,这是不同的故事,UTF-8 使用单顺序并将字符长度编码为第一个字符的第一位的模式。 UTF-8 编码在 Wikipedia 上有很好的描述。一般来说,设计是为了避免 endian'ess
问题UTF-16 和 UTF-32 编码不指定字节顺序。在 8 位字节流中,代码点 U+FEFF 可以用 UTF-16 编码为字节 FE, FF(大端)或 FF, FE(小端)。流编写器显然不知道流将在哪里结束(一个文件、一个网络套接字、一个本地程序?)所以你在开头放一个 BOM 来帮助 reader(s) 确定编码和 byte-order变体。
UTF-8 没有这种歧义,因为它从一开始就是一种 byte-oriented 编码。在 UTF-8 中编码此代码点的唯一方法是按此精确顺序使用字节 EF、BB、BF。 (方便的是,序列化的第一个字节的高位也揭示了序列将占用多少字节。)