UTF-8和不带BOM的UTF-8有什么区别?


818

没有BOM的 UTF-8和UTF-8有什么区别?哪个更好?


77
与内容清单相比,通过内容更好地自动检测UTF-8。该方法很简单:尝试以UTF-8格式读取文件(或字符串),如果成功,则假定数据为UTF-8。否则,假定它为CP1252(或其他一些8位编码)。几乎可以肯定,任何非UTF-8八位编码都将包含UTF-8不允许的序列。纯ASCII(7位)被解释为UTF-8,但结果也是如此。
Tronic

39
扫描大型文件以获取UTF-8内容需要花费时间。BOM使该过程更快。在实践中,您经常需要同时做这两项。如今的罪魁祸首是,仍然有很多文本内容不是Unicode,而我仍然碰到说它们支持Unicode(例如UTF-8)但以不同的代码页发出其内容的工具。
Jeroen Wiert Pluimers 2013年

10
@Tronic我真的不认为“更好”适合这种情况。这取决于环境。如果你确信所有的UTF-8的文件都标有一个BOM不是检查BOM“更好”的方式,因为它是更快,更可靠。
mg30rg

32
UTF-8没有BOM。当您在UTF-8文件的开头放置U + FEFF代码点时,必须格外小心。这只是Microsoft命名的谎言之一,例如在没有这种名称时调用编码“ Unicode”。
tchrist 2014年

7
“现代的大型机(和AIX)不了解 UTF-8的字节序” UTF-8没有局限性!周围没有字节改组以将成对或成组的四对成特定系统的正确“顺序”!要检测UTF-8字节序列,可能需要注意的是,多字节序列“代码点”的第一个字节(不是“普通” ASCII的字节)已设置了MS位,并且又将所有的位设置为一到三依次依次为低有效位和复位位。这些设置位的总数减去该代码点中的字节数,然后将全部设置MSB ...
SlySven

Answers:


773

UTF-8 BOM是文本流()开头的字节序列,0xEF, 0xBB, 0xBF它使读者可以更可靠地猜测文件是否以UTF-8编码。

通常,BOM用于表示编码的字节序,但是由于字节序与UTF-8不相关,因此BOM是不必要的。

根据Unicode标准不建议使用UTF-8文件BOM

2.6编码方案

... UTF-8既不需要也不建议使用BOM,但是在从使用BOM的其他编码形式转换UTF-8数据或BOM用作UTF-8签名的情况下可能会遇到BOM。 。有关更多信息请参见第16.8节特价 ”中的“字节顺序标记”小节。


114
可能不建议这样做,但根据我在希伯来语转换中的经验,BOM有时对于在Excel中识别UTF-8至关重要,并且可能使Jibrish和希伯来语
马坦亚

26
可能不建议这样做,但是当尝试输出“æøå”时,它确实使我的Powershell脚本感到惊讶
Marius

63
不管标准是否推荐它都是允许的,而且我非常喜欢让某些东西充当UTF-8签名,而不是假设或猜测的替代方式。兼容Unicode的软件应该/必须能够处理它的存在,因此我个人鼓励使用它。
martineau 2013年

30
@ bames53:是的,在理想情况下,将文本文件的编码存储为文件系统元数据是一种更好的保存方式。但是生活在现实世界中的大多数人都无法更改程序在其上运行的OS的文件系统-因此,使用Unicode标准的独立于平台的BOM签名似乎是最好,最实用的替代IMHO。
martineau 2014年

34
@martineau就在昨天,我遇到了一个带有UTF-8 BOM的文件,该文件不是UTF-8(是CP936)。不幸的是,那些由UTF-8 BOM造成的巨大痛苦的人基本上没有意识到。
bames53 2014年

243

其他出色的答案已经回答:

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

但是,作为对此的附加信息,如果字符串以UTF-8编码,则UTF-8的BOM可能是“嗅觉”的好方法...或者它可以是任何其他编码形式的合法字符串...

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

  • 合法的ISO-8859-1字符串“ABC”
  • 合法的UTF-8字符串“ ABC”

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

编码应该是已知的,而不是不可分割的。


60
@Alcott:您理解正确。字符串[EF BB BF 41 42 43]只是一堆字节。您需要外部信息来选择如何解释它。如果您认为这些字节是使用ISO-8859-1编码的,则字符串为“ABC”。如果您认为这些字节是使用UTF-8编码的,则为“ ABC”。如果您不知道,则必须尝试找出答案。BOM可能是一个线索。当解码为UTF-8时,缺少无效字符可能是另一个原因……最后,除非您能以某种方式记忆/查找编码,否则字节数组就是字节数组。
paercebal 2011年

19
@paercebal虽然“我»¿”是有效的Latin-1,这是非常不可能的文本文件开头部分的组合。ucs2-le / be标记ÿþ和同样适用。您也永远不会知道。
user877329 2013年

16
@deceze在语言上可能是无效的:首先-(没关系),然后是一些引号,中间没有空格(不是可以)。¿表示它是西班牙文,但ï不使用西班牙文。结论:它不是拉丁文1,其确定性远高于没有它的确定性。
2013年

20
@user当然,这不一定有意义。但是,如果您的系统依赖于猜测,那么不确定性就会到来。一些恶意用户故意提交以这三个字母开头的文本,而您的系统突然认为它正在使用BOM来查看UTF-8,将文本视为UTF-8,它应该使用Latin-1,并且会进行一些Unicode注入。只是一个假设的例子,但肯定是可能的。您无法根据其内容,句号来判断文本编码。
deceze

40
“编码应该是已知的,而不是不可分割的。” 问题的核心和灵魂。+1,先生。换句话说:要么标准化您的内容,然后说:“我们一直在使用这种编码。句点。以这种方式编写。以这种方式阅读”,或者开发一种扩展格式,允许将编码存储为元数据。(后者可能也需要一些“引导程序标准编码”。就像说“告诉您编码的部分始终是ASCII。”)
jpmc26,2015年

135

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

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

而且,正如其他人提到的那样,拥有BOM表来检测某物是否为UTF-8既不充分,也没有必要:

  • 这是不够的,因为任意字节序列可能会以构成BOM的确切序列开头。
  • 这是没有必要的,因为您可以像读取字节一样将它们当作UTF-8读取。如果成功,按照定义,它是有效的UTF-8。

8
请参考第1点“不包含任何文本的文件将不再为空,因为它们始终包含BOM”,这(1)将OS文件系统级别与已解释的内容级别放在一起,加上它(2)错误地假定使用BOM时,必须放置一个BOM也会出现在每个其他空文件中。(1)的实际解决方案是不做(2)。从本质上讲,投诉减少为“可以将BOM表不切实际地放入原本为空的文件中,从而阻止最容易地检测到逻辑上为空的文件(通过检查文件大小)”。仍然有一个好的软件应该能够处理它。
干杯和健康。-Alf 2014年

7
关于第2点,“保存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字节值的工具一起使用。可能更好的解决方案是抛弃那些不好的工具。
干杯和健康。-Alf 2014年

8
关于第3点,“不可能将多个文件连接在一起,因为每个文件的开头都有BOM”,这是错误的。将UTF-8文件与BOM连接起来没有问题,因此很可能。我想也许您是说Unix-land cat不会给您一个干净的结果,这个结果仅在开始时才包含BOM。如果您这样说,那是因为cat在字节级别上工作,而不是在解释的内容级别上工作,并且以类似的方式cat不能处理照片。仍然没有太大的伤害。这是因为BOM编码的是零宽度的不间断空格。
干杯和健康。-Alf 2014年

19
@ Cheersandhth.-Alf这个答案是正确的。您只是在指出Microsoft错误。
tchrist 2014年

9
@brighty:不过通过添加Bom并不能改善这种情况。
Deduplicator 2015年

84

以下是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编码中的相同两个字节表示,包括UTF-8,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第8.1节

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

BOM在JSON中是多余的

不仅在JSON中是非法的,而且不需要确定字符编码,因为存在更可靠的方法来明确确定任何JSON流中使用的字符编码和字节序(有关详细信息,请参见此答案)。

BOM破坏了JSON解析器

它不仅在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,它也会拒绝输入,因为它的开头不是ASCII字符<128,这与RFC所要求的相同。

其他数据格式

不需要JSON中的BOM,这是非法的,并且会破坏根据RFC正常运行的软件。那时不使用它应该是一个明智的选择,但是总有些人坚持通过使用BOM,注释,不同的引用规则或不同的数据类型来破坏JSON。当然,任何人都可以自由使用BOM或其他任何需要的东西-那就不要将其称为JSON。

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

BOM的其他用途

至于JSON或脚本之外的用途,我认为这里已经有很好的答案。我想添加有关脚本和序列化的更详细的信息,因为这是导致实际问题的BOM字符的示例。


5
取代rfc4627的rfc7159实际上表明支持BOM可能不是那么邪恶。基本上没有BOM是一个模棱两可的难题,因此不支持Unicode的旧Windows和Unix软件仍然可以处理utf-8。
埃里克·格兰奇

2
听起来像JSON需要更新才能支持它,与Perl脚本,Python脚本,Ruby脚本和Node.js相同。仅仅因为这些平台选择不提供支持,并不一定会终止BOM的使用。苹果几年来一直试图杀死Adobe,而Adobe仍然存在。但是一个启发性的帖子。
htm11h

12
@EricGrange,您似乎非常支持BOM,但是没有意识到这将使无处不在的,通用的,最小的 “纯文本”格式成为UTF8之前版本的遗物!根据定义,将任何类型的(带内)标头添加到文本流中,都会对最简单的文本文件施加强制性协议,从而使其不再是“最简单”的文件!为了什么呢?为了支持所有其他没有签名的古老CP编码,因此您可能会误认为UTF-8?(顺便说一句,ASCII也是UTF-8。所以,BOM也一样?;)来吧。)
Sz。

2
这个答案就是我提出这个问题的原因!我在Windows中创建我的bash脚本,将这些脚本发布到Linux时遇到很多问题!杰森文件也是如此。
Tono Nam

2
我希望我可以将这个答案最多投票50次。我还要补充一点,此时,UTF-8赢得了标准之战,几乎所有在互联网上产生的文本都是UTF-8。一些最受欢迎的编程语言(例如C#和Java)在内部使用UTF-16,但是当使用这些语言的程序员将文件写入文件以输出流时,它们几乎总是将其编码为UTF-8。因此,拥有BOM标记UTF-8文件不再有意义。UTF-8应该是您在读取时使用的默认值,并且只有在UTF-8解码失败时才尝试其他编码。
rmunn

51

没有BOM的UTF-8和UTF-8有什么区别?

简短答案:在UTF-8中,物料清单被编码为字节 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。

哪个更好?

没有。正如Martin Cote回答的那样,Unicode标准不建议这样做。它会导致非BOM感知软件出现问题。

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


8
这也会使其中带有单个错误字节的有效UTF-8无效,尽管:/
endolith 2012年

8
-1关于“这会导致非BOM感知软件出现问题。”,这对我来说从来不是问题,但是相反,缺少BOM会导致BOM感知软件(尤其是Visual C ++)出现问题。问题。因此,该声明是特定于平台的,是狭义的Unix观点,但被误导为似乎适用于一般情况。它没有。
干杯和健康。-Alf 2014年

6
不,UTF-8没有BOM。这个答案是不正确的。请参阅Unicode标准。
tchrist

2
您甚至可以只看字节就认为自己有一个纯ASCII文件。但这也可能是utf-16文件,您必须在其中查看字而不是字节。现代软件应注意BOM。如果检测到无效序列,可以使用较小序列的代码点或替代的代码点,仍然无法读取utf-8。对于utf-16,当有孤立的替代物时,阅读可能也会失败。
Brighty

1
@Alf,我不同意您对非BOM态度的解释,即“ 特定平台,狭窄的Unix观点”。对我来说,胸襟狭could的唯一办法就是“ Unix领域”,如果MS和Visual C ++早于* NIX,而他们却没有。那MS(我假设故意)使用UTF-8而不是UTF-16 BOM开始的事实表明,我认为他们提升突破shperlg++,和其他许多自由和强大的工具。想要工作吗?只需购买 MS版本。MS产生了特定于平台的问题,就像\ x80- \ x95范围的灾难一样。
bballdave025

30

具有BOM的UTF-8可以更好地识别。我已经很难得出这个结论。我正在一个项目中,结果之一是一个CSV文件(包括Unicode字符)。

如果保存的CSV文件没有BOM表,则Excel会认为它是ANSI并显示乱码。一旦在前面添加了“ EF BB BF”(例如,通过使用带有UTF-8的记事本重新保存它;或带有UTF-8的BOM表使用Notepad ++重新保存),Excel就会很好地打开它。

RFC 3629建议将BOM表字符添加到Unicode文本文件中:“ UTF-8,ISO 10646的转换格式”,2003年11月,网址为http://tools.ietf.org/html/rfc3629(此最新信息位于:http://www.herongyang.com/Unicode/Notepad-Byte-Order-Mark-BOM-FEFF-EFBBBF.html


6
感谢您提供的出色技巧,以防万一正在创建供Excel使用的UTF-8文件。但是,在其他情况下,我仍然会遵循其他答案并跳过BOM。
barfuin

5
如果您创建的文件仅包含ASCII,并且以后可能添加了非ASCII,则它也很有用。我刚遇到一个问题:期望utf8的软件会创建包含一些数据的文件供用户编辑。如果初始文件仅包含ASCII,则在某些编辑器中将其打开然后保存,则该文件将以latin-1结尾,并且一切都会中断。如果添加BOM,则编辑器会将其检测为UTF8,一切正常。
罗伯托·阿尔西纳

1
我发现了许多与编程相关的工具,这些工具需要BOM正确识别UTF-8文件。Visual Studio,SSMS,SoureTree ....
kjbartel

5
您在哪里阅读有关在该RFC中使用BOM 的建议最多建议强烈禁止在某些情况下禁止这样做。
Deduplicator 2015年

8
Excel认为它是ANSI并显示乱码,那么问题在Excel中。
以撒

17

BOM倾向于在某处某处繁荣(没有双关语)。而且当它蓬勃发展时(例如,未被浏览器,编辑器等识别),它会在文档开始时显示为奇怪的字符(例如,HTML文件,JSON响应,RSS等)。并导致这种尴尬,如奥巴马在Twitter上的谈话中最近遇到的编码问题

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


是的,只是花了几个小时来确定由文件编码为UTF-8而不是没有BOM的UTF-8引起的问题。(该问题仅出现在IE7中,这使我大为追杀。我使用了Django的“ include”。)
user984003 2013年

未来的读者:请注意,我上面提到的tweet问题与BOM并不严格相关,但如果确实如此,则该tweet会以类似的方式出现乱码,但在tweet的开头。
HalilÖzgür13年

12
@ user984003不,问题是Microsoft误导了您。它所谓的UTF-8不是UTF-8。没有BOM的UTF-8就是UTF-8的真正含义。
tchrist

“原文如此”添加到您的“非双关语”中是什么?
JoelFan

2
@JoelFan我已经不记得了,但我想尽管作者提出了要求,双关语还是有意的:)
HalilÖzgür17年

17

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

这是Wikipedia文章中有关字节顺序标记(BOM)的一些摘录,我相信这些摘录可为该问题提供可靠的答案。

关于BOM和UTF-8的含义:

Unicode标准允许BOMUTF-8 ,但不要求或建议其使用。字节顺序在UTF-8中没有任何意义,因此它在UTF-8中的唯一用途是一开始就表示文本流已以UTF-8编码。

使用BOM的参数

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

参数 FOR 使用BOM:

使用BOM的理由是,如果没有BOM,则需要进行启发式分析以确定文件正在使用的字符编码。从历史上看,这种区分各种8位编码的分析很复杂,容易出错,有时速度很慢。有许多库可简化任务,例如Mozilla通用字符集检测器和Unicode国际组件。

程序员错误地认为检测UTF-8同样困难(这不是因为绝大多数字节序列都是无效的UTF-8,而这些库试图区分的编码允许所有可能的字节序列)。因此,并非所有支持Unicode的程序都执行这种分析,而是依赖BOM。

特别是,Microsoft编译器和解释器以及Microsoft Windows上的许多软件(例如记事本)将无法正确读取UTF-8文本,除非它只有ASCII字符或以BOM表开头,并且在保存时将BOM表添加到开头文字为UTF-8。将Microsoft Word文档下载为纯文本文件时,Google文档将添加BOM。

使用 BOM表 使用BOM表哪个更好

IETF建议,如果一个协议或者(a)始终使用UTF-8,或(b)具有一些其它方式来指示正在使用什么编码,然后将其“应该禁止使用U + FEFF作为签名”。

我的结论:

使用BOM当与软件应用程序的兼容性是绝对必要的。

还要注意,尽管参考的维基百科文章指出许多Microsoft应用程序都依赖BOM来正确检测UTF-8,但并非所有 Microsoft应用程序都如此。例如,如@barlop所指出的那样,当将Windows命令提示符与UTF-8 †一起使用时,诸如typemore不希望BOM存在的命令。如果BOM 本,它可以是有问题的,因为它是用于其他应用。


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


5
我最好严格不使用BOM。我发现,.htaccessgzip compression在使用UTF-8 BOM组合给出了一个编码错误更改编码以UTF-8无BOM后续的建议作为解释在这里解决问题
Chetabahana

1
“不使用BOM的另一个动机是鼓励将UTF-8用作“默认”编码。-这是一个如此有力且有效的论据,以至于您实际上可能在那里停止了答案!...;-o除非您对通用文本表示有一个更好的主意。;)(我不知道您多大了,在UTF8之前的时代中您必须遭受多少年的痛苦(当语言学家拼命考虑甚至改变他们的字母时),但是我可以告诉您,我们每一刻都在逐渐消失所有古老的无元数据单字节编码的混乱,而不是拥有“一个”纯属喜悦。)
Sz。

另请参阅此评论有关如何添加一个BOM(或任何东西!),以最简单的文本文件格式,“纯文本”,将意味着严格的预防最好的通用文本编码格式被“普通”和“简单”(即“无头”)!...
Sz。

BOM在Linux上主要存在问题,因为许多实用程序实际上并没有真正支持Unicode(例如,它们会很高兴地在代码点中间截断)。对于大多数其他现代软件环境,只要编码无歧义(通过规范或元数据),请使用BOM。
埃里克·格兰奇

9

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

如上所述,在确定字符串是否为UTF-8时对UTF BOM(字节顺序标记)的任何使用都是有根据的猜测。是否有适当的元数据(例如charset="utf-8"),那么您已经知道应该使用什么,否则,您需要测试并做一些假设。这涉及检查字符串来自的文件是否以十六进制字节码EF BB BF开头。

如果找到了对应于UTF-8 BOM的字节码,则概率很高,可以假定它是UTF-8,您可以从那里开始。但是,如果被迫做出这种猜测,那么在读取时进行额外的错误检查仍然是一个好主意,以防万一出现乱码。如果绝对不应将 BOM表不是UTF-8(即latin-1或ANSI),则应假定基于其来源的。但是,如果没有BOM,则可以通过对编码进行验证来简单地确定它是否应为UTF-8。

为什么不建议使用BOM?

  1. 不支持Unicode或不兼容的软件可能会认为它是latin-1或ANSI,并且不会从字符串中删除BOM,这显然会引起问题。
  2. 并不是真正需要的(只需检查内容是否符合要求,当找不到符合要求的编码时,始终使用UTF-8作为后备)

什么时候应该使用BOM编码?

如果您无法以其他任何方式(通过字符集标记或文件系统元数据)记录元数据,并且无法像BOM一样使用程序,则应使用BOM进行编码。在Windows上尤其如此,在Windows上,通常假定没有BOM的任何东西都在使用旧版代码页。BOM告诉Office之类的程序,是的,该文件中的文本为Unicode。这是使用的编码。

说到它,我真正真正遇到过的唯一文件是CSV。根据程序,它要么必须具有BOM,要么必须没有BOM。例如,如果您在Windows上使用Excel 2007+,则要平滑打开它而不必求助于导入数据,则必须使用BOM对其进行编码。


2
答案的最后一部分是100%正确的:使用BOM 的唯一原因是当您必须与没有使用UTF-8作为默认文件来解析未知文件的越野车软件进行互操作时。
rmunn19年

8

请注意,对于某些文件,即使在Windows上也必须没有 BOM。示例是SQL*plusVBScript文件。如果此类文件包含BOM表,则在尝试执行它们时会出错。


8

仅当文件实际包含一些非ASCII字符时,带BOM的UTF-8才有用。如果包含该文件,则不存在任何文件,那么它可能会破坏以前将文件解释为纯ASCII的旧应用程序。这些应用程序遇到非ASCII字符时肯定会失败,因此,我认为BOM仅应在文件可以且不应再解释为纯ASCII的情况下添加。

我想说明的是,我完全不希望使用BOM。如果一些旧的垃圾没有垃圾就添加了它,那么替换该遗留应用程序是不可行的。

不要期望UTF-8有BOM。


7

在BOM表的Wikipedia页面底部引用:http : //en.wikipedia.org/wiki/Byte-order_mark#cite_note-2

“对于UTF-8,既不需要也不建议使用BOM,但是在从使用BOM的其他编码形式转换UTF-8数据或BOM用作UTF-8签名的情况下,可能会遇到BOM的情况。”


2
您是否有任何示例,其中软件会根据其以前的编码是否有BOM来决定是否使用UTF-8(带/不带BOM)?这似乎是荒唐的说法
barlop

7

没有BOM的UTF-8没有BOM,这不会比带有BOM的UTF-8更好,除非文件的使用者需要知道(或会从中获知)文件是否为UTF-8编码或不。

BOM通常可用于确定编码的字节序,这在大多数情况下不是必需的。

此外,对于那些不了解或不关心BOM的用户而言,BOM可能是不必要的噪音/痛苦,并可能导致用户困惑。


2
“它对于UTF-8毫无用处,因为它无论如何是每个字形8位。” 呃...不,只有ASCII-7字形在UTF-8中是8位。除此之外的任何内容都将是16位,24位或32位。
Powerlord

3
“ BOM通常对于确定编码的字节序很有用,这在大多数使用情况下是不需要的。” ...字节序根本不适用于UTF-8,无论使用情况如何
JoelFan

6

我从另一个角度看待这个问题。我认为带有BOM的UTF-8更好,因为它提供了有关文件的更多信息。仅当遇到问题时,我才使用不带BOM的UTF-8。

我长时间在页面上使用多种语言(甚至是西里尔字母),并且保存文件时没有使用BOM,然后重新打开文件以使用编辑器进行编辑(如cherouvim所述),某些字符已损坏。

请注意,Windows的经典记事本当您尝试使用UTF-8编码保存新创建的文件时自动使用BOM表保存文件。

我个人保存带有BOM的服务器端脚本文件(.asp,.ini,.aspx)带有BOM的.html文件


4
感谢您提供有关Windows经典记事本的出色技巧。我已经花了一些时间找出完全相同的东西。我的后果是总是使用Notepad ++而不是Windows经典的Notepad。:-)
barfuin

您最好使用madedit。如果您选择utf-8字节序列而不是字节和字符之间的1:1基础,那么它是唯一的编辑器-在十六进制模式下-显示一个字符。知道UTF-8文件的十六进制编辑器应该像madedit一样具有魅力!
Brighty

@brighty我认为您不需要BOM一对一。没关系,识别utf-8 BOM是efbbbf还是fffe(如果读错则为fffe)并不需要很多。只需删除这些字节即可。虽然为文件的其余部分建立了映射也不错,但是也能够逐字节删除
barlop

@barlop如果文件内容是utf-8编码的,为什么要删除utf-8 BOM?BOM被现代的文本查看器,文本控件以及文本编辑器识别。utf-8序列的一对一视图没有意义,因为n字节导致一个字符。当然,文本编辑器或十六进制编辑器应允许删除任何字节,但这会导致无效的utf-8序列。
Brighty

带有bom的@brighty utf-8是一种编码,而没有bom的utf-8是一种编码。cmd提示符使用不带bom的utf8 ..因此,如果您有utf8文件,请运行命令chcp 65001以获取utf8支持,它是不带bom的utf8。如果这样做type myfile,则只有在没有Bom的情况下,它才能正确显示。如果执行此操作echo aaa>a.aecho אאא>a.a 将字符输出到文件aa,并且具有chcp 65001,则它将输出而没有BOM。
barlop

6

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

但是当我们有文本CSV时情况并非如此在Windows或Linux上和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文件中。


1
FTM,以XML格式,我认为您应该将文件保留为ASCII并改为使用实体
Alois Mahdal

4
我知道这是一个旧答案,但是我只想提一下这是错误的。Linux上的文本文件(不能代表其他Unix)通常为/ are / UTF-8。
Functino

6

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

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

响应shebang行,指定要使用的外壳:

#!/bin/bash

如果另存为UTF-8,那么所有BOM(例如BBEdit中的内容)都不会很好。


8
那是因为微软已经交换了标准所说的含义。UTF-8没有BOM:他们创建了Microsoft UTF-8,该Microsoft UTF-8在数据流的前面插入了一个伪造的BOM,然后告诉您不,这实际上是UTF-8。它不是。它只是在扩展和腐败。
tchrist

4

如上所述,带有BOM的UTF-8可能会导致非BOM感知(或兼容)软件出现问题。我曾经使用基于Mozilla的KompoZer编辑了编码为UTF-8 + BOM的HTML文件,因为客户端需要所见即所得程序。

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

另外,我刚刚在Wikipedia中找到了这个:

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


4

Unicode 字节顺序标记(BOM)常见问题解答提供了一个简洁的答案:

问:我应该如何处理BOM?

答:以下是一些指导原则:

  1. 特定协议(例如,Microsoft .txt文件约定)可能要求在某些Unicode数据流(例如文件)上使用BOM。当您需要遵循此类协议时,请使用BOM。

  2. 对于未加标签的文本,某些协议允许使用可选的BOM。在那种情况下

    • 如果已知文本数据流是纯文本,但编码方式未知,则BOM可用作签名。如果没有BOM,则编码可以是任何形式。

    • 如果已知文本数据流是纯Unicode文本(而不是哪个字节序),则BOM可用作签名。如果没有BOM,则文本应解释为big-endian。

  3. 某些面向字节的协议期望在文件开头使用ASCII字符。如果这些协议使用UTF-8,则应避免使用BOM作为编码形式签名。

  4. 在已知数据流的确切类型的地方(例如Unicode大端或Unicode小端),不应使用BOM。特别是,无论何时将数据流声明为UTF-16BE,UTF-16LE,UTF-32BE或UTF-32LE,都不得使用BOM。


1

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,这会在以后的开发链中引起其他问题。


9
确保在不支持BOM的软件的开头出现乱码字节。好极了。
罗曼(Romain)2010年

1
@Romain Muller:例如,当您尝试在BOM表之后发送标头时,PHP 5将抛出“不可能”错误。
Piskvor于

5
αβγ不是ascii,但可以以8位为基础的编码中出现。BOM的使用会禁用utf-8的功能,utf-8与ascii的兼容性(能够在使用纯ascii的延迟应用程序中使用)。
ctrl-alt-delor

1
这是错误的答案。前面带有BOM表的字符串完全是另外一回事。它不应该在那里,只需将所有东西拧紧。
tchrist

如果没有BOM,则在大多数编辑器中以ANSI的形式打开。我完全同意。如果发生这种情况,很幸运,如果您处理正确的代码页,但实际上只是个猜测,因为代码页不是文件的一部分。BOM是。
Brighty

1

这是我对Visual Studio,Sourcetree和Bitbucket拉取请求的经验,这给了我一些问题:

因此事实证明,在审查拉动请求时,带有签名的BOM将在每个文件上包含一个红点字符(可能会很烦人)。

在此处输入图片说明

如果将鼠标悬停在它上面,它将显示类似“ ufeff”的字符,但事实证明Sourcetree不显示这些类型的字节标记,因此它很可能最终出现在您的请求中,这应该没问题,因为这就是Visual Studio的方式2017现在对新文件进行编码,因此Bitbucket可能会忽略此文件或以其他方式显示它,更多信息请参见:

红点标记BitBucket差异视图


-4

如果在HTML文件中使用UTF-8,并且在同一页面上使用塞尔维亚西里尔字母,塞尔维亚拉丁字母,德语,匈牙利语或某些外来语言,则带有BOM的UTF更好。

我的观点是(计算机和IT行业已有30年的历史)。


1
我发现这也是正确的。如果您使用第一个255个ASCII字符集之外的字符,而忽略了BOM,则浏览器会将其解释为ISO-8859-1,并且您会得到乱码。鉴于以上给出的答案,这显然是在浏览器供应商未检测到BOM时做错了事情。但是除非您使用Microsoft Edge / Mozilla / Webkit / Blink,否则别无选择,只能使用这些应用程序所存在的缺陷进行处理。
asontu

UTF是什么?UTF-8?UTF-16?还有别的吗
Peter Mortensen
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.