首页 文章

没有BOM的UTF-8和UTF-8有什么不同?

提问于
浏览
671

没有BOM的UTF-8和UTF-8有什么不同?哪个更好?

20 回答

  • 7

    在某个地方,某些地方,BOM往往会繁荣(没有双关语意图(原文如此)) . 当它激增时(例如,浏览器,编辑器等无法识别),它会在文档的开头显示为奇怪的字符  (例如,HTML文件,JSON响应,RSS等 . )并导致像recent encoding issue experienced during the talk of Obama on Twitter这样的尴尬 .

    当它出现在难以调试的地方或者忽略测试时,它会非常烦人 . 因此除非必须使用它,否则最好避免使用它 .

  • 7

    我从不同的角度看待这个问题 . 我认为 UTF-8 with BOM is better 因为它提供了有关该文件的更多信息 . 如果我遇到问题,我只使用没有BOM的UTF-8 .

    我长时间在我的页面上使用多种语言(甚至是Cyrillic),当文件保存而没有BOM时,我重新打开它们以便使用编辑器进行编辑(如cherouvim也注明),某些字符已损坏 .

    请注意,当您尝试使用UTF-8编码保存新创建的文件时,Windows的经典Notepad会自动保存带有BOM的文件 .

    我个人保存服务器端 scripting files (.asp, .ini, .aspx) with BOM.html files without BOM .

  • 106

    可以更好地识别带有BOM的UTF-8 . 我用艰难的方式得出了这个结论 . 我正在开发一个项目,其中一个结果是CSV文件,包括Unicode字符 .

    如果保存的CSV文件没有BOM,则Excel认为它是ANSI并显示乱码 . 一旦你在前面添加“EF BB BF”(例如,使用带有UTF-8的记事本重新保存它;或者使用带有BOM的UTF-8记事本),Excel就可以正常打开它 .

    RFC 3629:"UTF-8, a transformation format of ISO 10646",2003年11月在http://tools.ietf.org/html/rfc3629推荐将BOM字符预先添加到Unicode文本文件中(最后一个信息位于:http://www.herongyang.com/Unicode/Notepad-Byte-Order-Mark-BOM-FEFF-EFBBBF.html

  • 12

    Unicode Byte Order Mark (BOM) FAQ提供了一个简明的答案:

    问:我应该如何处理物料清单?答:以下是一些要遵循的准则:特定协议(例如.txt文件的Microsoft约定)可能需要在某些Unicode数据流(例如文件)上使用BOM . 如果需要符合此类协议,请使用BOM . 某些协议允许在未标记文本的情况下使用可选BOM . 在这些情况下,如果已知文本数据流是纯文本,但编码未知,则可以将BOM用作签名 . 如果没有BOM,则编码可以是任何内容 . 如果已知文本数据流是纯Unicode文本(但不是哪个字节序),那么BOM可以用作签名 . 如果没有BOM,则应将文本解释为big-endian . 一些面向字节的协议期望文件开头的ASCII字符 . 如果UTF-8与这些协议一起使用,则应避免使用BOM作为编码形式签名 . 如果已知数据流的精确类型(例如Unicode big-endian或Unicode little-endian),则不应使用BOM . 特别是,无论何时将数据流声明为UTF-16BE,UTF-16LE,UTF-32BE或UTF-32LE,都不得使用BOM .

  • -3

    来自http://en.wikipedia.org/wiki/Byte-order_mark

    字节顺序标记(BOM)是一个Unicode字符,用于表示文本文件或流的字节顺序(字节顺序) . 它的代码点是U FEFF . BOM使用是可选的,如果使用,则应显示在文本流的开头 . 除了作为字节顺序指示符的特定用途之外,BOM字符还可以指示文本被编码的几个Unicode表示中的哪一个 .

    始终在文件中使用BOM将确保它始终在支持UTF-8和BOM的编辑器中正确打开 .

    没有BOM的真正问题如下 . 假设我们有一个包含以下内容的文件:

    abc
    

    没有BOM,这在大多数编辑器中以ANSI开头 . 因此,此文件的另一个用户打开它并附加一些本机字符,例如:

    abg-αβγ
    

    糟糕...现在文件仍然是ANSI并且猜测是什么,“αβγ”不占用6个字节,而是3.这不是UTF-8,这会在开发链中导致其他问题 .

  • 6

    这个问题已经有一百万个答案了,其中很多都很好,但我想尝试澄清何时应该或不应该使用BOM .

    如上所述,任何使用UTF BOM(字节顺序标记)来确定字符串是否为UTF-8都是受过教育的猜测 . 如果有适当的元数据(如 charset="utf-8" ),那么您已经知道需要测试和做出一些假设 . 这涉及检查字符串来自的文件是否以十六进制字节代码EF BB BF开头 .

    如果找到与UTF-8 BOM对应的字节代码,则概率足够高,可以假设它是UTF-8,您可以从那里开始 . 然而,当被迫做出这种猜测时,在阅读时进行额外的错误检查仍然是一个好主意,以防万一出现乱码 . 您应该只假设BOM不是UTF-8(即latin-1或ANSI),如果输入肯定不应该是UTF-8,基于它_S应该是UTF-8,通过验证编码 .

    为什么不建议使用BOM?

    • 非Unicode感知或不合规的软件可能会假设它从字符串中剥离BOM,这显然会导致问题 .

    • 并不是真的需要(只检查内容是否合规,并且在找不到兼容编码时始终使用UTF-8作为后备)

    何时应使用BOM进行编码?

    如果您无法以任何其他方式(通过charset标记或文件系统元素)和程序记录元数据像BOM一样使用时,您应该使用BOM进行编码 . 在Windows上尤其如此,通常假设没有BOM的任何内容都使用遗留代码页 . BOM告诉像Office这样的程序,是的,这个文件中的文本是Unicode;这是使用的编码 .

    归根结底,我遇到问题的唯一文件是CSV . 根据程序的不同,它必须或者必须没有BOM . 例如,如果您在Windows上使用Excel 2007,则必须使用BOM进行编码,如果要平滑打开它而不必使用导入数据 .

  • 6

    带BOM的UTF-8仅在文件实际包含一些非ASCII字符时才有用 . 如果它包含但没有,那么它可能会破坏旧文件,否则会将文件解释为纯ASCII . 这些应用程序在遇到非ASCII字符时肯定会失败,所以在我看来,只有当文件可以而且不应该被解释为纯ASCII时才应添加BOM .

    编辑:只是想明确表示我更愿意根本没有BOM,如果一些旧的垃圾破坏了它就加入它,并且替换那个遗留应用程序是不可行的 .

    不要期望UTF8的BOM .

  • 2

    将BOM放入UTF-8编码文件至少存在三个问题 .

    • 不包含文本的文件不再为空,因为它们始终包含BOM .

    • 包含UTF-8的ASCII子集内的文本的文件不再是ASCII,因为BOM不是ASCII,这使得一些现有工具崩溃,用户无法替换这些遗留工具 .

    • 无法将多个文件连接在一起,因为每个文件现在都有一个BOM .

    并且,正如其他人所提到的那样,使用BOM来检测某些东西是UTF-8既不充分也不必要:

    • 这是不够的,因为任意字节序列都可能以构成BOM的确切序列开始 .

    • 没有必要,因为你可以像读取UTF-8一样读取字节;如果成功,根据定义,它是有效的UTF-8 .

  • 635

    如果要显示以UTF-8编码的信息,可能不会遇到问题 . 例如,将HTML文档声明为UTF-8,您将在浏览器中显示包含在文档正文中的所有内容 .

    但是当我们在Windows或Linux上有文本,_521926和XML文件时,情况并非如此 .

    例如,Windows或Linux中的文本文件,可以想象的最简单的事情之一,它(通常)不是UTF-8 .

    将其另存为XML并将其声明为UTF-8:

    <?xml version="1.0" encoding="UTF-8"?>
    

    即使它被声明为UTF-8,它也不会正确显示(不会被读取) .

    我有一串包含法语字母的数据,需要保存为XML以进行联合 . 无需从头开始创建UTF-8文件(更改IDE中的选项和“创建新文件”)或在文件开头添加BOM

    $file="\xEF\xBB\xBF".$string;
    

    我无法将法语字母保存在XML文件中 .

  • 6

    在维基百科页面底部的BOM上引用:http://en.wikipedia.org/wiki/Byte-order_mark#cite_note-2

    “UTF-8既不要求也不建议使用BOM,但在使用BOM的其他编码形式或将BOM用作UTF-8签名的UTF-8数据转换的上下文中可能会遇到”

  • 5

    问题:没有BOM的UTF-8和UTF-8有什么不同?哪个更好?

    以下是关于byte order mark (BOM)的维基百科文章的一些摘录,我相信这个问题可以提供一个可靠的答案 .

    On the meaning of the BOM and UTF-8:

    Unicode标准允许使用UTF-8的BOM,但不要求或建议使用它 . 字节顺序在UTF-8中没有意义,因此它在UTF-8中的唯一用途是在开始时发信号通知文本流以UTF-8编码 .

    Argument for NOT using a BOM:

    不使用BOM的主要动机是向后兼容不支持Unicode的软件......不使用BOM的另一个动机是鼓励UTF-8作为“默认”编码 .

    Argument FOR using a BOM:

    使用BOM的论点是没有它,需要启发式分析来确定文件使用的字符编码 . 历史上,用于区分各种8位编码的这种分析是复杂的,容易出错的,并且有时是慢的 . 许多库可用于简化任务,例如Mozilla Universal Charset Detector和International Components for Unicode . 程序员错误地认为检测UTF-8同样困难(不是因为绝大多数字节序列都是无效的UTF-8,而这些库试图区分的编码允许所有可能的字节序列) . 因此,并非所有支持Unicode的程序都执行此类分析,而是依赖于BOM . 特别是,Microsoft编译器和解释器以及Microsoft Windows上的许多软件(如记事本)将无法正确读取UTF-8文本,除非它只有ASCII字符或以BOM开头,并且在保存时会添加BOM文字为UTF-8 . 当Microsoft Word文档作为纯文本文件下载时,Google文档将添加BOM .

    On which is better, WITH or WITHOUT the BOM:

    IETF建议,如果协议要么(a)总是使用UTF-8,要么(b)有其他方式来指示正在使用的编码,那么它“应该禁止使用U FEFF作为签名” .

    My Conclusion:

    如果与软件应用程序的兼容性绝对必要,请使用BOM only .

    另请注意,虽然引用的维基百科文章指出许多Microsoft应用程序依赖于BOM来正确检测UTF-8,但并非所有Microsoft应用程序都是如此 . 例如,正如@barlop所指出的,当使用带有UTF-8†的Windows命令提示符时,诸如 typemore 之类的命令不希望存在BOM . 如果BOM存在,则可能会出现问题,因为它适用于其他应用程序 .


    chcp命令通过代码页65001提供对UTF-8(无BOM)的支持 .

  • 59

    UTF-8 BOM是文本流(EF BB BF)开头的字节序列,允许读者更可靠地将文件猜测为以UTF-8编码 .

    通常,BOM用于表示编码的字节顺序,但由于字节顺序与UTF-8无关,因此BOM不是必需的 .

    根据Unicode standardBOM for UTF-8 files is not recommended

    2.6编码方案......对于UTF-8既不要求也不建议使用BOM,但在使用BOM的其他编码形式或使用BOM作为其他编码形式转换UTF-8数据的上下文中可能会遇到UTF-8签名 . 有关详细信息,请参见第16.8节“特价”中的“字节顺序标记”小节 .

  • 200

    应该注意的是,对于某些文件,即使在Windows上,您也可以使用BOM . 示例是 SQL*plusVBScript 文件 . 如果此类文件包含BOM,则在尝试执行它们时会出现错误 .

  • 46

    如果您在HTML文件中使用UTF-8,如果您在同一页面中使用塞尔维亚语西里尔语,塞尔维亚语拉丁语,德语,匈牙利语或某种外来语言,则使用带有BOM的UTF会更好 . 这是我的观点(30年的计算和IT行业) .

  • 29

    没有BOM的UTF-8没有BOM,除了当文件的消费者需要知道(或将从中获益)文件是否是UTF-8编码时,它不会比带有BOM的UTF-8更好 . 或不 .

    BOM通常用于确定编码的字节顺序,这在大多数用例中都不是必需的 .

    此外,对于那些不了解或不关心它的消费者来说,BOM可能是不必要的噪音/痛苦,并且可能导致用户混淆 .

  • 15

    这是一个很老的问题,有很多好的答案,但有一点需要补充 .

    所有答案都很一般 . 我想添加的是实际导致实际问题的BOM使用示例,但很多人并不了解它 .

    BOM破坏脚本

    Shell脚本,Perl脚本,Python脚本,Ruby脚本,Node.js脚本或需要由解释器运行的任何其他可执行文件 - 所有这些都以shebang line开头,看起来像其中之一:

    #!/bin/sh
    #!/usr/bin/python
    #!/usr/local/bin/perl
    #!/usr/bin/env node
    

    它告诉系统在调用这样的脚本时需要运行哪个解释器 . 如果脚本以UTF-8编码,则可能会想要在开头包含BOM . 但实际上"#!"字符不仅仅是字符 . 它们实际上是一个恰好由两个ASCII字符组成的magic number . 如果您在这些字符之前放置了某些内容(如BOM),那么该文件看起来会有不同的幻数,这可能会导致问题 .

    见维基百科,article: Shebang, section: Magic number

    shebang字符由扩展ASCII编码中的相同两个字节表示,包括UTF-8,它通常用于当前类Unix系统上的脚本和其他文本文件 . 但是,UTF-8文件可能以可选的字节顺序标记(BOM)开头;如果“exec”函数专门检测到字节0x23和0x21,那么在shebang之前存在BOM(0xEF 0xBB 0xBF)将阻止脚本解释器被执行 . 由于这个原因以及更广泛的互操作性和哲学问题,一些权威机构建议不要在POSIX(类Unix)脚本中使用字节顺序标记[14] . 此外,在UTF-8中不需要字节顺序标记,因为该编码没有字节顺序问题;它仅用于将编码标识为UTF-8 . [重点补充]

    BOM在JSON中是非法的

    RFC 7159, Section 8.1

    实现绝不能在JSON文本的开头添加字节顺序标记 .

    BOM在JSON中是多余的

    它不仅是JSON中的 illegal ,而且确定字符编码也是 not needed ,因为有更可靠的方法可以明确地确定任何JSON流中使用的字符编码和字节序(有关详细信息,请参阅this answer) .

    BOM破坏了JSON解析器

    它不仅是JSON中的 illegalnot needed ,它实际上 breaks all software 使用RFC 4627中提供的方法确定编码:

    确定JSON的编码和字节顺序,检查NUL字节的前4个字节:

    00 00 00 xx - UTF-32BE
    00 xx 00 xx - UTF-16BE
    xx 00 00 00 - UTF-32LE
    xx 00 xx 00 - UTF-16LE
    xx xx xx xx - UTF-8
    

    现在,如果文件以BOM开头,它将如下所示:

    00 00 FE FF - UTF-32BE
    FE FF 00 xx - UTF-16BE
    FF FE 00 00 - UTF-32LE
    FF FE xx 00 - UTF-16LE
    EF BB BF xx - UTF-8
    

    注意:

    • UTF-32BE无法识别

    • UTF-32LE第一个字节后面跟着3个NUL,因此无法识别

    • UTF-16BE在前4个字节中只有1个NUL,因此无法识别

    • UTF-16LE在前4个字节中只有1个NUL,因此无法识别

    根据实现的不同,所有这些都可能被错误地解释为UTF-8,然后被误解为或被拒绝为无效的UTF-8,或根本无法识别 .

    此外,如果实现测试有效的JSON,我建议,它甚至会拒绝确实编码为UTF-8的输入,因为它不是以ASCII字符<128开头,因为它应该根据RFC .

    其他数据格式

    不需要JSON中的BOM,这是违法的,并且会破坏根据RFC正常工作的软件 . 如果不使用它应该是一个nobrainer然而,总有人坚持使用BOM,评论,不同的引用规则或不同的数据类型来破坏JSON . 当然,如果你需要的话,任何人都可以自由地使用BOM或其他东西 - 只是不要把它称为JSON .

    对于除JSON之外的其他数据格式,请查看它的真实情况 . 如果唯一的编码是UTF- *且第一个字符必须是低于128的ASCII字符,那么您已经拥有了确定数据的编码和字节序所需的所有信息 . 即使作为可选功能添加BOM也只会使其更复杂且容易出错 .

    BOM的其他用途

    至于JSON或脚本之外的用途,我认为这里已有非常好的答案 . 我想添加更详细的脚本和序列化信息,因为它是导致实际问题的BOM字符的一个例子 .

  • 6

    一个实际的区别是,如果你为Mac OS X编写一个shell脚本并将其保存为普通的UTF-8,你将得到响应:

    #!/bin/bash: No such file or directory
    

    响应shebang行指定您要使用的shell:

    #!/bin/bash
    

    如果您保存为UTF-8,则没有BOM(例如BBEdit)都可以 .

  • 5

    其他优秀的答案已经回答:

    • UTF-8和BOM-ed UTF-8之间没有官方差异

    • BOM-ed UTF-8字符串将以以下三个字节开头 . EF BB BF

    • 从文件/流中提取字符串时,必须忽略这些字节(如果存在) .

    但是,作为附加信息,如果字符串是以UTF-8编码的话,UTF-8的BOM可能是“闻”的好方法......或者它可能是任何其他编码中的合法字符串......

    例如,数据[EF BB BF 41 42 43]可以是:

    因此,虽然通过查看第一个字节来识别文件内容的编码可能很酷,但您不应该依赖于此,如上面的示例所示

    Encodings should be known, not divined.

  • 3

    没有BOM的UTF-8和UTF-8有什么不同?

    简答:在UTF-8中,BOM被编码为文件开头的字节 EF BB BF .

    答案很长:

    最初,预计Unicode将以UTF-16 / UCS-2编码 . BOM是为此编码表单设计的 . 当你有2字节的代码单元时,有必要指出这两个字节在哪个顺序,这样做的一个通用约定是在数据的开头包含字符U FEFF作为"Byte Order Mark" . 字符U FFFE永久未分配,因此可以使用它的存在来检测错误的字节顺序 .

    无论平台字节顺序如何,UTF-8都具有相同的字节顺序,因此不需要字节顺序标记 . 但是,在从UTF-16转换为UTF-8的数据中,或者作为"signature"表示数据为UTF-8时,可能会发生(如字节序列 EF BB FF ) .

    哪个更好?

    没有 . 正如Martin Cote回答的那样,Unicode标准不推荐它 . 它会导致非BOM感知软件出现问题 .

    检测文件是否为UTF-8的更好方法是执行有效性检查 . UTF-8对什么字节序列有效有严格的规则,因此误报的概率可以忽略不计 . 如果一个字节序列看起来像UTF-8,它可能是 .

  • 2

    正如刚才提到的,带BOM的UTF-8可能会导致非BOM感知(或兼容)软件出现问题 . 我曾经用基于Mozilla的KompoZer编辑了编码为UTF-8 BOM的HTML文件,作为客户端需要WYSIWYG程序 .

    保存时,布局总是会被破坏 . 花了我一些时间来摆弄这个问题 . 这些文件在Firefox中运行良好,但在Internet Explorer中显示了一个CSS怪癖,再次破坏了布局 . 在摆弄链接的CSS文件数小时后无济于事,我发现Internet Explorer不喜欢BOMfed HTML文件 . 再也不 .

    另外,我刚在维基百科发现了这个:

    shebang字符由扩展ASCII编码中的相同两个字节表示,包括UTF-8,它通常用于当前类Unix系统上的脚本和其他文本文件 . 但是,UTF-8文件可能以可选的字节顺序标记(BOM)开头;如果“exec”函数专门检测到字节0x23 0x21,那么在shebang之前存在BOM(0xEF 0xBB 0xBF)将阻止脚本解释器被执行 . 一些权威机构建议不要在POSIX(类Unix)脚本中使用字节顺序标记[15],因为这个原因以及更广泛的互操作性和哲学问题

相关问题