UTF-8 BOM是文本流开头的一系列字节(0xEF, 0xBB, 0xBF
),可以使读者更可靠地猜测文件是否以UTF-8编码。
通常,BOM用于标志编码的字节序,但由于字节序与UTF-8无关,因此BOM是不必要的。
根据Unicode标准,不建议为UTF-8文件使用BOM:
2.6 编码方案
... 不需要也不建议在UTF-8中使用BOM,但在将UTF-8数据从使用BOM的其他编码形式转换或将BOM用作UTF-8签名的情况下可能会遇到。有关更多信息,请参见 第16.8节“特殊符号”中的“字节顺序标记”子节。
其他优秀的回答已经解释:
EF BB BF
但是,作为这个问题的额外信息,UTF-8的BOM可以是“嗅探”一个字符串是否被编码为UTF-8的好方法......或者它可能是任何其他编码的合法字符串...
例如,数据[EF BB BF 41 42 43] 可以是:
因此,虽然通过查看前几个字节识别文件内容的编码可能很酷,但您不应该依赖它,如上面的示例所示
编码应该是已知的,而不是半信半疑的。
在UTF-8编码的文件中放置BOM至少存在三个问题。
正如其他人提到的那样,拥有BOM并不足以且也不必要用它来检测是否为UTF-8:
cat
命令无法给出一个干净的结果,即只在开头有BOM的结果。如果是这个意思的话,那是因为cat
命令在字节级别上工作,而不是在解释内容级别上工作,同样地,cat
命令也无法处理照片之类的东西。但它并不会造成太大的影响。这是因为BOM编码了一个零宽度的不间断空格。 - Cheers and hth. - AlfShell脚本、Perl脚本、Python脚本、Ruby脚本、Node.js脚本或任何需要由解释器运行的可执行文件都以shebang行开头,如下所示:
#!/bin/sh
#!/usr/bin/python
#!/usr/local/bin/perl
#!/usr/bin/env node
实现必须不在JSON文本开头添加字节顺序标记。
BOM在JSON中不仅是非法的,而且也不必要,因为有更可靠的方法可以明确确定任何JSON流中使用的字符编码和字节顺序(有关详细信息,请参见this answer)。
BOM在JSON中不仅是非法的和不必要的,它实际上还会破坏所有软件,这些软件使用RFC 4627中提出的方法来确定编码:
检测JSON的编码和字节顺序,检查前四个字节是否为NUL字节:
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
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-8,然后被误解或拒绝作为无效的 UTF-8,或者根本不被识别。
此外,如果实现按照我推荐的方式测试有效的 JSON,则即使输入确实被编码为 UTF-8,也将被拒绝,因为它不像 RFC 中应该的那样以 ASCII 字符 < 128 开头。
对于JSON以外的其他数据格式,请看看它实际上是什么样子的。如果唯一的编码方式是UTF-*,并且第一个字符必须是小于128的ASCII字符,则已经具备了确定数据的编码和字节顺序的所有信息。即使将BOM作为可选功能添加也只会使它更加复杂和容易出错。
至于JSON或脚本之外的用途,我认为这里已经有非常好的答案了。我想添加更详细的信息,特别是关于脚本和序列化,因为这是BOM字符导致真正问题的一个例子。
sh
、perl
、g++
和许多其他免费且强大的工具的做法。想要一切正常?只需购买MS版本即可。MS创造了平台特定的问题,就像他们\x80-\x95范围的灾难一样。 - bballdave025带有BOM的UTF-8更易识别。我通过艰难的方式得出了这个结论。我正在处理一个包含Unicode字符的CSV文件的项目。
如果CSV文件没有保存BOM,Excel认为它是ANSI编码并显示乱码。在文件开头添加"EF BB BF"(例如,使用带有BOM的UTF-8重新保存它,或者使用Notepad++等工具),Excel便可以正常打开它。
在RFC 3629中推荐在Unicode文本文件前加上BOM字符:“UTF-8,ISO 10646的转换格式”,2003年11月,网址:https://www.rfc-editor.org/rfc/rfc3629(此信息来源于:http://www.herongyang.com/Unicode/Notepad-Byte-Order-Mark-BOM-FEFF-EFBBBF.html)
使用BOM的理由:
使用BOM的理由是,如果没有它,就需要启用启发式分析来确定文件所使用的字符编码。历史上,为了区分各种8位编码而进行的这种分析是复杂、容易出错且有时很慢的。有许多库可用于简化这个任务,例如Mozilla通用字符集检测器和Unicode国际组件。关于使用BOM,哪种更好,带还是不带:
IETF建议如果协议要么(a)总是使用UTF-8编码,或者(b)有其他方式指示正在使用的编码,则“应禁止使用U+FEFF作为签名”。
我的结论:
仅当与软件应用程序的兼容性绝对必要时才使用BOM。
请注意,虽然参考的维基百科文章表明许多微软应用程序依赖BOM正确检测UTF-8,但并非所有微软应用程序都是如此。例如,正如@barlop所指出的,在使用带UTF-8†的Windows命令提示符时,诸如type
和more
等命令不需要BOM存在。如果存在BOM,则可能会对其他应用程序产生问题,请注意。
chcp
命令通过代码页 65001 支持 UTF-8(不带 BOM)。.htaccess
和gzip压缩
与UTF-8 BOM一起使用时会出现编码错误。按照这里的建议,改为使用UTF-8 Without BOM编码可以解决这些问题。 - eQ19BOM(字节顺序标记)往往会在某些地方迅速兴起(不是说笑话)。当它出现问题时(例如,浏览器、编辑器等无法识别),它会显示为文档开头的奇怪字符
(例如,HTML文件、JSON响应、RSS等),并引起像最近Twitter上讨论奥巴马问题时的编码问题这样的尴尬。
当它出现在难以调试或测试被忽略的地方时,这非常令人恼火。因此,除非必须使用它,否则最好避免使用它。
这个问题已经有了无数的答案,其中许多都很好,但我想试着澄清何时应该使用BOM。
如前所述,在确定字符串是否为UTF-8时,任何对UTF BOM(字节顺序标记)的使用都是基于猜测的。如果有可用的正确元数据(例如 charset="utf-8"
),那么你已经知道应该使用什么,否则你需要进行测试并作出一些假设。这涉及检查源文件的起始十六进制字节代码是否以EF BB BF开头。
如果发现与UTF-8 BOM相对应的字节码,那么可以高度推断它是UTF-8,然后可以按照此方式处理。然而,当被迫进行这种猜测时,阅读时进行额外的错误检查仍然是一个好主意,以防出现乱码。只有在输入明确不应该是UTF-8(即拉丁1或ANSI)时,才能假定没有BOM是不是UTF-8。然而,如果没有BOM,你可以通过对编码进行验证来确定它是否应该是UTF-8。
如果你无法以其他方式记录元数据(通过charset标签或文件系统元数据),且正在使用的程序喜欢BOM,则应该使用带有BOM的编码。在Windows上尤其如此,因为没有BOM的任何内容通常被认为是使用传统代码页。BOM告诉Office之类的程序:是的,此文件中的文本是Unicode;使用的编码是什么。
说到底,我遇到问题的文件只有CSV。根据程序的不同,CSV文件必须或不能使用BOM编码。例如,如果您在Windows上使用Excel 2007+,如果要平稳地打开它而不必通过导入数据来解决问题,则必须使用BOM进行编码。