【问题标题】:Why BOM is U+FE FF, rather than U+FF FE?为什么 BOM 是 U+FE FF,而不是 U+FF FE?
【发布时间】:2016-07-21 12:34:07
【问题描述】:

所以我正在自学字符编码,我有一个大概很愚蠢的问题:Wikipedia

字节顺序标记(BOM)是一个Unicode字符,U+FEFF BYTE ORDER 马克(BOM),...

,并且该页面上的图表显示

Encoding      Representation (hexadecimal)  
UTF-8         EF BB BF  
UTF-16 (BE)   FE FF  
UTF-16 (LE)   FF FE  
...

我对此有点困惑。据我所知,大多数使用 Intel CPU 的机器都是 little-endian,那么为什么 BOM 是 UTF-16 (BE) 的 U+FE FF,而不是 UTF-8 的 U+EF BB BF 或 UTF-16 (LE) 的 U+FF FE

【问题讨论】:

  • 好吧,因为 U+FEFF 是一个字符,而 U+FFEF 不是。零宽度空间有一个很好的属性,即即使应用程序没有正确过滤它或通过在文本流中间插入 BOM 来混淆,它也不会影响呈现的文本。非常常见的错误。
  • 关于你的“UTF-8 而不是 U+EF BB BF”:很有趣,因为 UTF8 不需要“字节顺序标记”。 UTF8 编码文本中的所有值都应该正好是 1 个字节长,因此出错的可能性为零。
  • @RadLexus 所以 UTF-8 不需要 BOM 来指示字节顺序,而 UTF-16 和 UTF-32 则需要?
  • 是的。 wikipedia 上有一篇相当长的文章讨论所有品种。

标签: unicode utf-8 character-encoding


【解决方案1】:

为什么 BOM 对于 UTF-16 (BE) 是 U+FE FF

不是。 BOM 是字符编号 U+FEFF。没有空格,它是一个十六进制数字,也就是 65279。这个定义不依赖于用什么字节序列来表示任何特定编码中的字符。

在UTF-16LE中编码字符(*)的字节序列的十六进制表示,0xFE, 0xFF与字符号U+FEFF的十六进制表示具有相同的数字顺序;这只是大端的人工制品,它将最重要的内容放在左边,就像人类对大 [hexa] 十进制数字所做的那样。

(* 以及基本多语言平面中的任何字符。当您超出此范围时,它会变得更加毛茸茸,因为它们不再适合两个字节。)

【讨论】:

    【解决方案2】:

    据我所知,大多数使用 Intel CPU 的机器都是 little-endian

    英特尔 CPU 并不是世界上唯一使用的 CPU。 AMD、ARM 等。还有大端 CPU。

    为什么 BOM 是 UTF-16 (BE) 的 U+FE FF,而不是 UTF-8 的 U+EF BB BF 或 UTF-16 (LE) 的 U+FF FE?

    U+FEFF 是 Unicode 代码点名称。 FE FFEF BB BFFF FE,这些是字节序列。 U+ 仅适用于 Unicode 代码点指定,而不适用于字节。

    Unicode 代码点U+FEFF ZERO WIDTH NO-BREAK SPACE(这是它的官方名称,而不是U+FEFF BYTE ORDER MARK,虽然它用作BOM)的数值是@987654329 @ (65279)。

    以 UTF-8 编码的代码点值生成三个 8 位代码单元值 0xEF 0xBB 0xBF,它们不受任何字节序问题的影响,这就是 UTF-8 没有单独的 LE 和 BE 变体的原因。

    以 UTF-16 编码的相同代码点值会生成一个 16 位代码单元值 0xFEFF。因为它是一个多字节(16 位)值,所以当解释为两个 8 位字节时,它受字节序的影响,因此有 LE (0xFF 0xFE) 和 BE (0xFE 0xFF) 变体。

    受影响的不仅仅是 BOM。 UTF-16 字符串中的所有代码单元都受字节序的影响。 BOM 帮助解码器了解用于整个字符串中的代码单元的字节序。

    UTF-32,它也使用多字节(32 位)代码单元,也受字节序的约束,因此它也有 LE 和 BE 变体,以及一个 32 位 BOM 来向解码器表达该字节序(@ LE 为 987654334@,BE 为 0x00 0x00 0xFE 0xFF)。是的,正如您可能猜到的那样,如果您不提前知道要处理的是哪种 UTF,那么 UTF-16LE BOM 和 UTF-32LE BOM 之间存在歧义。 BOM 旨在识别字节序,因此名称为“Byte Order Mark”,而不是特定的编码(尽管它通常用于该目的)。

    【讨论】:

    • 可能还值得一提的是,U+FFFE 不是有效的 Unicode 代码点,这就是为什么 U+FEFF 可以用作字节顺序标记(否则无法可靠区分)。 “endian”应该是“endianness”。
    • 我确实看到 U+FEFF 在 Unicode 3.2 中已被弃用,因为它支持 U+2060 WORD JOINER 用于此目的的中断字符。但是,Unicode 规范也确实规定,如果 U+FEFF 出现在字符串中,则仍应将其视为断路器:“Unicode 3.2 实现应支持此新字符 [U+2060],但也支持U+FEFF的ZWNBSP语义."
    • 您是否误读了我的评论? U+FEFF 是一个有效字符(零宽度无间隔),用作 BOM。 U+FFFEnot 有效字符,或者至少没有分配给它的名称(参见 [UnicodeData.txt](unicode.org/Public/UNIDATA/UnicodeData.txt, 1.6MB文本文件) -- 这就是为什么 U+FEFF 可以用作 BOM。如果你看到 U+FFFE,它可能是一个字节交换的 BOM,你需要更改您用来解释输入的字节序。(“endian”是形容词;“endianness”是对应的名词。)
    • 是的,我误读了您的评论。是的,如果你将一个 2 字节的 BOM 读入一个 16 位的变量并得到一个 0xFFFE 的值,那么这个 BOM 的字节序与你所读的相反。
    • 那可以写fputwc(L'\uFEFF', fp);添加BOM吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-09-13
    • 1970-01-01
    • 1970-01-01
    • 2019-07-26
    • 2019-10-01
    • 1970-01-01
    • 2017-03-01
    相关资源
    最近更新 更多