【问题标题】:Why would I use a Unicode Signature Byte-Order-Mark (BOM)?为什么要使用 Unicode 签名字节顺序标记 (BOM)?
【发布时间】:2010-11-05 22:48:09
【问题描述】:

这些已经过时了吗?它们似乎是有史以来最糟糕的想法——在文件内容中嵌入任何人都看不到的东西,但会影响文件的功能。我不明白我为什么想要一个。

【问题讨论】:

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


    【解决方案1】:

    在某些情况下它们是必要的,是的,因为 UTF-16 既有 little-endian 也有 big-endian 实现。

    当读取一个未知的 UTF-16 文件时,你怎么知道使用的是哪一个? 唯一的解决方案是在文件中放置某种易于识别的标记,无论使用哪种字节序,都不会被误认为是其他任何东西。

    这就是 BOM 的作用。

    你需要一个吗?仅当您是 1) 在字节序存在问题的情况下使用 UTF 编码(这对 UTF-16 很重要,但无论字节序如何,UTF8 总是看起来相同),并且文件将被共享与外部应用程序。

    如果您自己的应用程序是唯一要读取和写入文件的应用程序,您可以省略 BOM,只需一劳永逸地决定您要使用哪种字节序。但如果另一个应用程序必须读取文件,它不会提前知道字节序,因此添加 BOM 可能是个好主意。

    【讨论】:

    • UTF-8 中不需要 BOM。它把事情搞砸了。想象一下cat file1 file2 file3 > file123
    • @tchrist:嗯,是的。在 7 位 ASCII 或 JPG 图像中也不需要它们。这就是为什么我的回答非常明确地谈到了 UTF-16。
    【解决方案2】:

    Unicode 联盟UTF and BOM FAQ 的一些摘录可能会有所帮助。

    问:什么是 BOM?

    答: 字节顺序标记 (BOM) 由字符代码 U+FEFF 在数据流的开头 组成,可用作签名定义字节顺序和编码形式,主要是未标记的纯文本文件。在某些更高级别的协议下,在该协议中定义的 Unicode 数据流中可能强制(或禁止)使用 BOM。 (强调我的。)

    我不会确切地说字节顺序标记是嵌入数据中的。相反,它为数据添加前缀。当字符是数据流中的第一件事时,它只是一个字节顺序标记。其他任何地方,它是 零宽度不间断空间。不尊重字节顺序标记的 Unicode 感知程序无论如何都不会受到它的存在的真正伤害,因为字符是不可见的,并且在文本块开头的单词连接器只会将下一个字符连接到任何内容,所以没有效果。

    问:BOM 有什么用处?

    答: BOM 在以文本形式键入的文件的开头很有用,但不知道它们是大端还是小端格式 - 它也可以用作提示文件是 Unicode,而不是传统编码,此外,它充当所使用的特定编码形式的签名。

    因此,当您的程序能够处理 Unicode 的多种编码时,您会需要一个 BOM。您的程序在解释其输入时如何知道使用哪种编码?

    问:当使用 BOM 时,它是否只有 16 位 Unicode 文本?

    答: 不,无论 Unicode 文本如何转换,BOM 都可以用作签名:UTF-16、UTF-8、UTF-7 等。包含BOM 将是由该转换格式转换成的任何 Unicode 字符 U+FEFF。在这种形式中,BOM 用于指示它是一个 Unicode 文件,以及它是哪种格式。

    这可能是当今最常使用 BOM 的情况。它将 UTF-8 编码的文本与任何其他编码区分开来;它并没有真正标记字节的顺序,因为 UTF-8 只有一个顺序。

    如果您正在设计自己的协议或数据格式,则不需要使用 BOM。常见问题解答中的另一个问题涉及到这一点:

    问:如何标记不将 U+FEFF 解释为 BOM 的数据?

    答:使用标签 UTF-16BE 表示大端 UTF-16 文本,使用 UTF-16LE 表示小端 UTF-16 文本。如果您确实使用 BOM,请将文本标记为简单的 UTF-16。

    它提到了标记数据格式的概念。这意味着从数据本身指定格式带外。如果您可以使用这样的工具,那就太好了,但通常不是这样,尤其是在为 Unicode 改造旧系统时。

    【讨论】:

      【解决方案3】:

      当您使用 UTF-8 标记此内容时,我会说您不需要 BOM。 Byto Order Marks 仅对 UTF-16 和 UTF-32 有用,因为它会通知计算机文件是否在 Big Endian or Little Endian 中。一些文本编辑器可能会使用字节顺序标记来决定文档使用什么编码,但这不是 Unicode 标准的一部分。

      【讨论】:

        【解决方案4】:

        BOM 表示文件采用哪种 Unicode 编码。没有这种区别,Unicode 阅读器将不知道如何读取文件。

        但是,UTF-8 不需要 BOM。

        查看Wikipedia article

        【讨论】:

        • 字节顺序标记不表示 Unicode 版本。 Unicode 目前是 5.1 版,5.2 版正在测试中,但 BOM 保持不变。
        • @Rob 我的意思是编码(UTF-8、16、32 等以及字节序)。我的意思不是 5.1、5.2 等。我改变了我的答案以反映。
        • 我怀疑维基百科的文章只是偏向于 *nix 人。他们引用的问题可能源于盲目地将 UTF-8 视为 ANSI 并希望达到最佳状态的软件。如果你问我,有点种族中心主义。这可能是使用 BOM 的一个优势:假设编码为 ANSI 时,无法识别 UTF-8 BOM 的软件将无法工作。
        • @Bob:为什么cat 需要关心编码是什么?
        • ANSI?为什么 *nix 软件会将任何东西都视为 ANSI?这是微软主义的意思,意思是“ASCII 的几个 8 位扩展之一,但你必须猜是哪一个”。 *nix 软件更可能采用 ASCII 或 UTF-8没有 BOM,Unicode 联盟不鼓励使用。
        【解决方案5】:

        “BOM”是 Unicode 早期的遗留物,当时人们认为使用 Unicode 意味着使用 16 位字符。在像 UTF-8 这样只有一个字节顺序的编码中完全没有意义。 U+FEFF 的选择对于 UTF-32 也是次优的,因为它无法区分所有可能的中端字节顺序(这样做需要用 4 个不同字节编码的 BOM)。

        您使用 UTF-16 或 UTF-32 数据的唯一原因是在具有不同字节顺序的平台之间发送 UTF-16 或 UTF-32 数据,但是 (1) 大多数人仍然使用 UTF-8,以及 (2) MIME charset参数提供了更好的机制。

        【讨论】:

          【解决方案6】:

          UTF16 和 UTF32 可以写成 Big-Endian 和 Little-Endian 形式。您可以尝试通过分析以任一字节序处理文件的结果来启发式地确定字节序,但为了省去您的麻烦,BOM 可以立即告诉您。

          UTF-8 并不真正需要 BOM,因为您逐字节解码它。

          【讨论】:

            【解决方案7】:

            无论您是否在创建文本文件时自己使用这些,在您阅读文本文件时可能都值得注意。即在文件开头检测并跳过(并理想地处理)BOM。我遇到了一些它,最初导致了我的一些问题,直到我弄清楚发生了什么。

            【讨论】:

              【解决方案8】:

              由于 UTF16 和 UTF32 BOM 可以判断内容是 Big-Endian 还是 Little-Endian 格式,并且内容是 Unicode,UTF-8 BOM 将文件分类为 utf-8 编码。如果没有 UTF-8 BOM,你怎么知道它是 ANSI 文件还是 UTF-8 编码文件? UTF-8 BOM 当然不会告诉字节序,因为 utf-8 始终是字节流,但它会告诉内容是 utf-8 编码的 Unicode 还是 ANSI。当然,您可以扫描有效的 utf-8 序列,但在我看来,检查文件的前三个字节更容易。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2011-10-30
                • 2011-04-21
                • 1970-01-01
                • 2012-05-22
                • 2017-01-28
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多