UTF-8 and UTF-8 with BOM are both character encoding schemes, but they have a slight difference. UTF-8 is a widely used encoding that represents characters using variable-length sequences of bytes. It does not include a Byte Order Mark (BOM) at the beginning of the file. On the other hand, UTF-8 with BOM includes a BOM, which is a specific sequence of bytes (0xEF, 0xBB, 0xBF) placed at the beginning of the file to indicate that it is encoded in UTF-8. The BOM can be useful for applications that need to detect the encoding of a file automatically. However, it is not always necessary and can sometimes cause issues, especially in certain programming languages or environments.

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

88
使用内容比使用BOM更能自动检测UTF-8编码。这种方法很简单:尝试将文件(或字符串)以UTF-8编码读取,如果成功,则假定数据为UTF-8编码。否则,假定它是CP1252(或其他8位编码)。任何非UTF-8的8位编码几乎肯定包含UTF-8不允许的序列。纯ASCII(7位)会被解释为UTF-8,但也可以得到正确的结果。 - Tronic
50
扫描大文件以查找UTF-8内容需要时间。加上BOM能够使这个过程快很多。在实践中,通常需要两者兼备。现在的问题是仍然有很多文本内容不是Unicode,我仍然会遇到一些工具声称支持Unicode(如UTF-8),但实际输出的却是另一种编码方式。 - Jeroen Wiert Pluimers
11
@Tronic,我不认为“更好”适用于这种情况。这取决于环境。如果您确信所有UTF-8文件都带有BOM,则检查BOM是更好的方式,因为它更快且更可靠。 - mg30rg
39
UTF-8 没有 BOM。当你在 UTF-8 文件开头加上一个 U+FEFF 代码点时,必须特别注意处理它。这只是微软的一种虚假命名,就像称编码为“Unicode”一样,实际上并不存在这样的东西。 - tchrist
10
现代主机(和AIX)是小端UTF-8兼容的。UTF-8没有“字节序”!在特定系统中,没有对字节进行重排来将四个字节配对或分组放置在正确的“顺序”中!为了检测UTF-8字节序列,有用的方法可能是注意到多字节序列“码点”的第一个字节(不是“普通”ASCII字符的字节)具有MS位设置,并且所有接下来的三个比这一位更低有效位以及一个复位位。那些被设置的位的总数比该码点中的字节少一个,并且它们全部都有MSB设置... - SlySven
显示剩余12条评论
22个回答

981

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节“特殊符号”中的“字节顺序标记”子节。


150
这可能不是推荐的做法,但根据我在希伯来语转换方面的经验,BOM有时对于Excel中的UTF-8识别至关重要,可能会使乱码和希伯来语之间产生差异。 - Matanya
51
虽然可能不被推荐,但当我尝试输出“æøå”时,这确实对我的PowerShell脚本产生了奇妙的效果。 - Marius
81
尽管标准不推荐,但它是被允许的,我非常喜欢有一些东西作为UTF-8签名,而不是假设或猜测的替代方案。符合Unicode标准的软件应该/必须能够处理其存在,因此我个人鼓励使用它。 - martineau
34
是的,在理想的世界中,将文本文件的编码存储为文件系统元数据会更好地保存它。但是我们大多数人生活在现实世界中,无法更改操作系统文件系统的方式,因此使用Unicode标准的平台无关的BOM签名似乎是我认为最好和实用的替代方法。 - martineau
44
昨天我遇到了一个带有UTF-8 BOM但实际上不是UTF-8(而是CP936)的文件。不幸的是,导致UTF-8 BOM带来巨大痛苦的责任人很大程度上对此毫不知情。 - bames53
显示剩余26条评论

299

其他优秀的回答已经解释:

  • UTF-8和带BOM的UTF-8之间没有官方区别
  • 带BOM的UTF-8字符串将以以下三个字节开头:EF BB BF
  • 如果存在这些字节,从文件/流中提取字符串时必须忽略它们。

但是,作为这个问题的额外信息,UTF-8的BOM可以是“嗅探”一个字符串是否被编码为UTF-8的好方法......或者它可能是任何其他编码的合法字符串...

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

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

编码应该是已知的,而不是半信半疑的。


72
@Alcott:你理解得没错。字符串[EF BB BF 41 42 43]只是一组字节。你需要外部信息来选择如何解释它。如果你认为这些字节是使用ISO-8859-1编码的,那么这个字符串就是“ABC”。如果你认为这些字节是使用UTF-8编码的,那么它就是“ABC”。如果你不知道,那么你必须尝试找出来。BOM可能是一个线索。以UTF-8解码时没有无效字符也可能是另一个线索……最终,除非你能记住/找到编码方式,否则字节数组就只是一个字节数组。 - paercebal
24
@paercebal 虽然“”在 Latin-1 编码中是有效的,但一个文本文件以该组合开头的可能性非常小。同样的情况也适用于 ucs2-le/be 标记符号“ÿþ”和“þÿ”。此外,你永远无法确定。 - user877329
17
这句话可能在语言上不合法:首先是一个 ï(没问题),然后是一些没有空格的引号(不对)。¿ 表示这是西班牙语,但是 ï 不在西班牙语中使用。结论是:它不是 Latin-1,这个结论的确定性比没有这个结论高得多。 - user877329
29
@user 当然,这并不一定有意义。但是,如果您的系统依赖于“猜测”,那么就会存在不确定性。一些恶意用户有意提交以这三个字母开头的文本,使您的系统突然认为它正在查看带有BOM的UTF-8,并将文本作为UTF-8处理,而应该使用Latin-1,从而导致某些Unicode注入发生。这只是一个假设性的例子,但肯定是可能的。您无法通过其内容来判断文本编码。 - deceze
56
"编码应该被了解,而不是猜测。" 这是问题的核心。加一分,先生。换句话说:要么标准化你的内容并说,“我们总是使用这种编码。周期性。以这种方式写入和阅读,”或者开发一个扩展格式,允许将编码存储为元数据。(后者可能也需要一些“引导标准编码”。例如说,“告诉你编码的那部分总是ASCII编码。") - jpmc26
显示剩余21条评论

167

在UTF-8编码的文件中放置BOM至少存在三个问题。

  1. 不再为空的文件,因为它们始终包含BOM。
  2. 在UTF-8的ASCII子集内包含文本的文件不再是ASCII文件,因为BOM不是ASCII码,这会导致一些现有工具失效,并且用户可能无法替换此类旧工具。
  3. 无法将多个文件连接起来,因为每个文件现在都在开头有一个BOM。

正如其他人提到的那样,拥有BOM并不足以且也不必要用它来检测是否为UTF-8:

  • 不足以,因为任意字节序列可能恰好以构成BOM的确切序列开头。
  • 不必要,因为您可以将字节读取为如果它们是UTF-8;如果成功,则根据定义是有效的UTF-8。

12
关于第一点,"Files that hold no text are no longer empty because they always contain the BOM",这个观点(1)混淆了操作系统文件系统级别与解释后的内容级别,另外(2)错误地假定使用BOM必须在每个其他空文件中也放置BOM。对于问题(1),实际的解决方案是不要执行(2)。本质上,抱怨归结为“有可能在其他空文件中不切实际地放置BOM,从而防止通过检查文件大小最轻松地检测逻辑上的空文件”。然而,良好的软件应该能够处理它,因为它是有目的的。 - Cheers and hth. - Alf
10
关于第二点,“保存ASCII文本的文件不再是ASCII”这种说法混淆了ASCII和UTF-8。一个保存ASCII文本的UTF-8文件不是ASCII,它是UTF-8。同样地,一个保存ASCII文本的UTF-16文件也不是ASCII,它是UTF-16。ASCII是7位单字节编码,而UTF-8是ASCII的8位可变长度扩展。如果“工具”无法处理大于127的值,那么它们就不适用于8位世界。一个简单实用的解决方案是只使用ASCII文件和那些不能处理非ASCII字节值的工具。也许更好的解决方案是放弃那些不好的工具。 - Cheers and hth. - Alf
9
关于第三点,“不可能将多个文件连接在一起,因为每个文件现在都有一个BOM在开头”是错误的。我没有问题将带有BOM的UTF-8文件连接起来,所以显然是可行的。我认为你可能是指Unix环境下的cat命令无法给出一个干净的结果,即只在开头有BOM的结果。如果是这个意思的话,那是因为cat命令在字节级别上工作,而不是在解释内容级别上工作,同样地,cat命令也无法处理照片之类的东西。但它并不会造成太大的影响。这是因为BOM编码了一个零宽度的不间断空格。 - Cheers and hth. - Alf
32
这个答案是正确的。你只是指出了微软的漏洞。 - tchrist
14
即使添加一个BOM(字节顺序标记),情况也不会有所改善。 - Deduplicator
显示剩余11条评论

138
这里列举了一些BOM使用的实际问题,然而许多人并不知道它存在。

BOM会破坏脚本

Shell脚本、Perl脚本、Python脚本、Ruby脚本、Node.js脚本或任何需要由解释器运行的可执行文件都以shebang行开头,如下所示:

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

它告诉系统在调用此类脚本时需要运行哪个解释器。如果脚本以UTF-8编码,人们可能会想在开头包含一个BOM。但实际上,“#!”字符不仅仅是字符,它们实际上是一个魔数,由两个ASCII字符组成。如果在这些字符之前放置了一些东西(如BOM),那么该文件看起来就像具有不同的魔数,这可能会导致问题。
参见维基百科,Shebang文章,魔数部分
{shebang}字符在扩展ASCII编码中被表示为相同的两个字节,包括常用于当前类Unix系统上的脚本和其他文本文件的UTF-8。然而,UTF-8文件可能以可选的字节顺序标记(BOM)开头;如果"exec"函数明确检测到0x23和0x21字节,则在shebang之前存在BOM(0xEF 0xBB 0xBF)将防止执行脚本解释器。一些权威机构建议出于这个原因以及更广泛的互操作性和哲学问题不要在POSIX(类Unix)脚本中使用字节顺序标记。此外,在UTF-8中不需要字节顺序标记,因为该编码没有字节序问题;它只用于标识编码为UTF-8。[强调添加]

JSON中不允许使用BOM

请参见RFC 7159, Section 8.1

实现必须不在JSON文本开头添加字节顺序标记。

JSON中不需要BOM

BOM在JSON中不仅是非法的,而且也不必要,因为有更可靠的方法可以明确确定任何JSON流中使用的字符编码和字节顺序(有关详细信息,请参见this answer)。

BOM会破坏JSON解析器

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

现在,如果文件以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

请注意:
  1. UTF-32BE 不以三个 NUL 开头,因此它不会被识别
  2. UTF-32LE 第一个字节后面没有三个 NUL,因此它不会被识别
  3. UTF-16BE 在前四个字节中只有一个 NUL,因此它不会被识别
  4. UTF-16LE 在前四个字节中只有一个 NUL,因此它不会被识别

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

此外,如果实现按照我推荐的方式测试有效的 JSON,则即使输入确实被编码为 UTF-8,也将被拒绝,因为它不像 RFC 中应该的那样以 ASCII 字符 < 128 开头。

其他数据格式

在JSON中不需要BOM,使用BOM是非法的,并会破坏根据RFC正确工作的软件。因此,不使用它应该是很容易的选择,但总有人坚持通过使用BOM、注释、不同的引用规则或不同的数据类型来破坏JSON。当然,如果你需要使用像BOM这样的东西或其他任何东西-只是不要称其为JSON。

对于JSON以外的其他数据格式,请看看它实际上是什么样子的。如果唯一的编码方式是UTF-*,并且第一个字符必须是小于128的ASCII字符,则已经具备了确定数据的编码和字节顺序的所有信息。即使将BOM作为可选功能添加也只会使它更加复杂和容易出错。

BOM的其他用途

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


7
RFC7159取代RFC4627,实际上建议支持BOM可能并不那么糟糕。基本上,没有BOM只是一种含糊的权宜之计,以便不支持Unicode的旧Windows和Unix软件仍然可以处理utf-8编码。 - Eric Grange
23
@EricGrange,您似乎非常支持BOM,但未意识到这将使得普遍适用、广泛使用的最佳最小化“纯文本”格式成为过去的遗迹!向文本流添加任何形式的(内部)标头都将按定义强制实施协议到最简单的文本文件中,使它永远不再是“最简单”的!而为了什么收益?支持所有其他古老的CP编码,它们也没有签名,因此您可能会将它们误认为是UTF-8?(顺便说一下,ASCII也是UTF-8。所以,对于它们也需要BOM吗?;) 别开玩笑了。) - Sz.
5
这个答案是我提出这个问题的原因!我在Windows上创建了我的Bash脚本,并且在将这些脚本发布到Linux时遇到了很多问题!JSON文件也是一样。 - Tono Nam
5
我希望我能够给这个答案点赞大约五十次。同时,我还想补充一点,目前UTF-8已经赢得了标准战争,在互联网上几乎所有的文本都是采用UTF-8编码的。一些最流行的编程语言(例如C#和Java)在内部使用的是UTF-16编码,但是当使用这些语言的程序员将文件写到输出流时,他们几乎总是将它们编码为UTF-8。因此,在标记UTF-8文件时不再需要BOM。在读取时,应该默认使用UTF-8,只有在UTF-8解码失败时才尝试其他编码方式。 - rmunn
4
@EricGrange - 真的吗?快速的谷歌搜索对我来说是相反的:https://dev59.com/4XE85IYBdhLWcg3wLAUV 是关于UTF-8 BOM在Eclipse中显示为字符(即Eclipse认为那里不应该有BOM,不知道该怎么处理它),而 https://dzone.com/articles/what-does-utf-8-bom-mean 则表示:“在Eclipse中,如果我们将默认编码设置为UTF-8,则会使用没有字节顺序标记(BOM)的普通UTF-8”。 有没有链接到讨论Eclipse在省略UTF-8 BOM时失败的地方? - rmunn
显示剩余8条评论

52
短答案:在UTF-8中,BOM被编码为文件开头的字节EF BB BF。
长答案:
最初,人们预计Unicode将以UTF-16 / UCS-2编码。 BOM是为此编码形式设计的。当您有2字节代码单元时,需要指示这两个字节的顺序,并且通常用于执行此操作的公共约定是在数据开头包括字符U + FEFF作为“字节顺序标记”。字符U + FFFE永久未分配,因此可以使用其存在来检测错误的字节顺序。
UTF-8具有相同的字节顺序,无论平台的字节顺序如何,因此不需要字节顺序标记。但是,它可能会出现(作为字节序列EF BB FF)在从UTF-16转换为UTF-8的数据中,或者作为“签名”表示数据为UTF-8。
哪个更好?
没有BOM。正如Martin Cote所回答的那样,Unicode标准不建议使用它。它会导致与不支持BOM的软件的问题。
检测文件是否为UTF-8的更好方法是执行有效性检查。UTF-8对于什么字节序列是有效的有严格的规则,因此误报的概率可以忽略不计。如果一个字节序列看起来像UTF-8,那么它很可能是UTF-8。

9
这也将使本来有效的UTF-8因为单个错误字节而失效,不过:/ - endolith
10
“它导致不支持BOM的软件出现问题。” 对我来说从来没有出现过这种问题,相反,缺少BOM会导致BOM-aware软件(特别是Visual C ++)出现问题。因此,这个陈述非常特定于平台,是狭隘的Unix视角,但被误导地呈现为适用于一般情况,而事实并非如此。” - Cheers and hth. - Alf
6
不,UTF-8没有BOM。这个答案是不正确的。请参考Unicode标准。 - tchrist
2
即使只看字节,你可能认为自己有一个纯ASCII文件。但这也可能是一个utf-16文件,你需要查看单词而不是字节。现代软件应该意识到BOM。但是,如果检测到无效序列、可以使用较小序列的代码点或代理的代码点,则读取utf-8可能会失败。对于utf-16,如果存在孤立的代理,阅读也可能会失败。 - brighty
3
@Alf,我不同意你对非BOM态度的解释,认为这是“平台特定,狭隘的Unix观点”。在我看来,如果MS和Visual C++出现在*NIX之前,那么这种狭隘主义只能存在于“Unix领域”中。事实上,MS(我认为是有意的)开始在UTF-8而不是UTF-16中使用BOM,这表明他们推广了破坏shperlg++和许多其他免费且强大的工具的做法。想要一切正常?只需购买MS版本即可。MS创造了平台特定的问题,就像他们\x80-\x95范围的灾难一样。 - bballdave025
显示剩余4条评论

37

带有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


7
感谢您提供这个出色的提示,以防创建供Excel使用的UTF-8文件。不过,在其他情况下,我仍会遵循其他答案并跳过BOM。 - barfuin
5
如果你创建的文件最开始只包含ASCII字符,但后续可能会添加非ASCII字符,添加BOM将有助于编辑器正确识别该文件为UTF8编码,防止出现保存后变成latin-1编码导致一切崩溃的问题。 - Roberto Alsina
1
我发现了多个编程相关的工具,需要BOM才能正确识别UTF-8文件。Visual Studio、SSMS、SoureTree... - kjbartel
10
你在哪里看到建议在RFC中使用BOM?最多只是强烈建议在某些情况下不要禁止使用BOM,因为这样做很困难。 - Deduplicator
15
如果Excel认为它是ANSI并显示乱码,则问题出在Excel中。 - user8017719
显示剩余3条评论

18
以下是关于字节顺序标记 (BOM)的维基百科文章摘录,它能够回答这个问题:
关于 BOM 和 UTF-8:
Unicode 标准允许在 UTF-8 中使用BOM,但不要求或建议使用。在 UTF-8 中,字节顺序没有意义,因此它在 UTF-8 中的唯一用途是在开头表示文本流以 UTF-8 编码。
不使用 BOM 的理由:
不使用 BOM 的主要动机是向后兼容不支持 Unicode 的软件...不使用 BOM 的另一个动机是鼓励将 UTF-8 作为“默认”编码。

使用BOM的理由:

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

关于使用BOM,哪种更好,还是不带

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

我的结论:

仅当与软件应用程序的兼容性绝对必要时才使用BOM

请注意,虽然参考的维基百科文章表明许多微软应用程序依赖BOM正确检测UTF-8,但并非所有微软应用程序都是如此。例如,正如@barlop所指出的,在使用带UTF-8的Windows命令提示符时,诸如typemore等命令不需要BOM存在。如果存在BOM,则可能会对其他应用程序产生问题,请注意。
chcp 命令通过代码页 65001 支持 UTF-8(不带 BOM)。

5
我最好坚持“无BOM”格式。我发现在使用.htaccessgzip压缩与UTF-8 BOM一起使用时会出现编码错误。按照这里的建议,改为使用UTF-8 Without BOM编码可以解决这些问题。 - eQ19
1
“不使用BOM的另一个动机是鼓励UTF-8作为“默认”编码。”这个观点非常强而有力,甚至可以在此停止回答!除非你有更好的通用文本表示方法。我不知道你多大年纪,在UTF8时代之前你经历了多少年的痛苦(语言学家甚至考虑过改变他们的字母表),但我可以告诉你,每一秒我们都在接近摆脱所有古老的单字节无元数据编码的混乱,而不是拥有“唯一”的编码,这是纯粹的喜悦。;)” - Sz.
请参考此评论,了解如何向最简单的文本文件格式“纯文本”添加BOM(或任何内容!)将意味着防止最好的通用文本编码格式成为“纯粹”和“简单”(即“无开销”)!... - Sz.
BOM 在 Linux 上大多数情况下会出现问题,因为许多实用程序本身并不支持 Unicode(例如,它们会在代码点中间截断)。对于大多数其他现代软件环境,请在编码不明确时(通过规范或元数据)使用 BOM。 - Eric Grange

17

BOM(字节顺序标记)往往会在某些地方迅速兴起(不是说笑话)。当它出现问题时(例如,浏览器、编辑器等无法识别),它会显示为文档开头的奇怪字符(例如,HTML文件、JSON响应、RSS等),并引起像最近Twitter上讨论奥巴马问题时的编码问题这样的尴尬。

当它出现在难以调试或测试被忽略的地方时,这非常令人恼火。因此,除非必须使用它,否则最好避免使用它。


是的,我花了几个小时才发现一个问题,原因是文件编码为UTF-8而不是UTF-8带BOM。(这个问题只在IE7中出现,所以我进行了一次相当费力的追踪。我使用了Django的“include”功能。) - user984003
未来的读者注意:我上面提到的推文问题并不严格与BOM相关,但如果是这样的话,那么推文将以类似的方式混淆,但在推文开头。 - Halil Özgür
15
不,问题在于Microsoft误导了你。它所称的UTF-8并不是真正的UTF-8。而它所说的无BOM的UTF-8才是真正的UTF-8。 - tchrist
“sic”在“no pun intended”中的作用是什么? - JoelFan
2
@JoelFan 我已经记不清了,但我猜这个双关语可能是有意为之的,尽管作者声称不是 :) - Halil Özgür

17

这个问题已经有了无数的答案,其中许多都很好,但我想试着澄清何时应该使用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。

为什么不建议使用BOM?

  1. 非Unicode感知或不合规的软件可能会认为它是拉丁1或ANSI,并不会从字符串中删除BOM,这显然可能会导致问题。
  2. 这真的不是必需的(只需要检查内容是否符合规范,并始终将UTF-8用作无法找到符合规范的编码时的回退)

何时应该使用带有BOM的编码?

如果你无法以其他方式记录元数据(通过charset标签或文件系统元数据),且正在使用的程序喜欢BOM,则应该使用带有BOM的编码。在Windows上尤其如此,因为没有BOM的任何内容通常被认为是使用传统代码页。BOM告诉Office之类的程序:是的,此文件中的文本是Unicode;使用的编码是什么。

说到底,我遇到问题的文件只有CSV。根据程序的不同,CSV文件必须或不能使用BOM编码。例如,如果您在Windows上使用Excel 2007+,如果要平稳地打开它而不必通过导入数据来解决问题,则必须使用BOM进行编码。


10
你回答的最后一部分是完全正确的:使用BOM的唯一原因是当你需要与存在缺陷的软件交互时,该软件不能将未知文件解析为UTF-8格式。 - rmunn

9
UTF-8 without BOM 没有BOM,在没有需要知道文件是否采用UTF-8编码的消费者时,它和UTF-8 with BOM 没有什么不同。
对于大多数使用情况而言,确定编码的字节序通常是无关紧要的,所以BOM并不是必须的。
另外,BOM 对于那些不了解或不关心它的消费者来说,只会带来噪声和痛苦,并且可能导致用户混淆。

3
“which has no use for UTF-8 as it is 8-bits per glyph anyway.”的意思是“由于每个字形都是8位,因此UTF-8对其没有用处。”但实际上,只有ASCII-7字形在UTF-8中是8位的。任何超出该范围的字形将使用16、24或32位。 - Powerlord
5
“BOM通常有助于确定编码的字节序,但对于大多数使用情况而言并非必需。无论使用情况如何,UTF-8都不适用字节序。” - JoelFan
一个需要知道的消费者被设计破坏了。 - Jasen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接