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

What's the difference between UTF-8 and UTF-8 with BOM?

提问人:simple 提问时间:2/9/2010 最后编辑:TylerHsimple 更新时间:9/21/2023 访问量:865999

问:

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

Unicode UTF-8 字符编码 字节顺序标记

评论

88赞 Tronic 2/11/2010
UTF-8 可以通过内容比通过 BOM 更好地自动检测。方法很简单:尝试以 UTF-8 格式读取文件(或字符串),如果成功,则假设数据为 UTF-8。否则,假设它是 CP1252(或其他一些 8 位编码)。几乎可以肯定的是,任何非 UTF-8 的 8 位编码都包含 UTF-8 不允许的序列。纯 ASCII(7 位)被解释为 UTF-8,但结果也是正确的。
50赞 Jeroen Wiert Pluimers 12/18/2013
扫描大文件中的 UTF-8 内容需要时间。BOM 使此过程更快。在实践中,您经常需要两者兼而有之。现在的罪魁祸首是仍然有很多文本内容不是Unicode,我仍然会遇到一些工具,这些工具说他们使用Unicode(例如UTF-8),但向它们的内容发出不同的代码页。
11赞 mg30rg 7/31/2014
@Tronic 我真的不认为“更好”适合这种情况。这取决于环境。如果您确定所有 UTF-8 文件都标有 BOM,那么检查 BOM“更好”的方法,因为它更快、更可靠。
39赞 tchrist 10/2/2014
UTF-8 没有 BOM。当您将 U+FEFF 代码点放在 UTF-8 文件的开头时,必须特别小心处理它。这只是Microsoft命名谎言之一,就像在没有这样的东西时将编码称为“Unicode”。
10赞 SlySven 8/20/2016
“现代大型机(和 AIX)几乎无法识别端序 UTF-8”UTF-8 没有终结性!对于特定系统,无需对字节进行洗牌即可将成对或四组放入正确的“顺序”中!要检测 UTF-8 字节序列,请注意多字节序列“代码点”(不是“普通”ASCII 字节的字节)的第一个字节设置了 MS 位,并且所有 1 到 3 个连续的低有效位后跟一个复位位。这些设置位的总数在该代码点中少了一个字节,并且它们都将设置 MSB...

答:

9赞 Romain 2/9/2010 #1

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

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

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

评论

3赞 Powerlord 2/9/2010
“这对 UTF-8 没有用处,因为它无论如何都是每个字形 8 位。” 呃......不可以,只有 ASCII-7 字形是 UTF-8 中的 8 位。超出此范围的任何内容都将是 16、24 或 32 位。
5赞 JoelFan 10/24/2017
“BOM 通常可用于确定编码的字节序,这在大多数用例中是不需要的。”...字节序根本不适用于 UTF-8,无论用例如何
0赞 Jasen 8/9/2020
一个需要知道的消费者被设计打破了。
4赞 cherouvim 2/9/2010 #2

来自 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,这会导致开发链后期出现其他问题。

评论

10赞 Romain 2/9/2010
确保虚假字节出现在非 BOM 感知软件的开头。耶。
1赞 Piskvor left the building 2/9/2010
@Romain Muller:例如.PHP当您尝试在 BOM 之后发送标头时,5 将抛出“不可能”的错误。
5赞 ctrl-alt-delor 1/7/2011
αβγ 不是 ASCII,但可以出现在 8 位 ASCII 低音编码中。使用 BOM 会禁用 utf-8 的 benafit,即它与 ascii 的兼容性(能够与使用纯 ascii 的滞后应用程序一起工作)。
1赞 tchrist 10/2/2014
这是错误的答案。前面有 BOM 的字符串完全是另一回事。它不应该在那里,只是把一切都搞砸了。
0赞 brighty 2/10/2015
如果没有 BOM,这在大多数编辑器中将作为 ANSI 打开。我完全同意。如果发生这种情况,如果您处理正确的代码页,您就很幸运了,但实际上这只是一个猜测,因为代码页不是文件的一部分。BOM 是。
979赞 Martin Cote 2/9/2010 #3

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

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

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

2.6 编码方案

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

评论

150赞 Matanya 12/7/2012
可能不推荐这样做,但根据我在希伯来语转换方面的经验,BOM 有时对于 Excel 中的 UTF-8 识别至关重要,并且可能会区分 Jibrish 和希伯来语
51赞 Marius 11/12/2013
可能不推荐它,但在尝试输出“æøå”时,它对我的 powershell 脚本产生了奇迹
81赞 martineau 1/1/2014
不管标准不推荐它,它都是允许的,我非常喜欢有一些东西作为 UTF-8 签名,而不是假设或猜测的替代方案。符合Unicode的软件应该/必须能够处理它的存在,所以我个人鼓励使用它。
34赞 martineau 1/17/2014
@bames53:是的,在理想情况下,将文本文件的编码存储为文件系统元数据是保存它的更好方法。但是,我们大多数人生活在现实世界中,无法更改运行程序的操作系统的文件系统 - 因此,恕我直言,使用Unicode标准的独立于平台的BOM签名似乎是最好和最实用的替代方案。
44赞 bames53 1/17/2014
@martineau 就在昨天,我遇到了一个 UTF-8 BOM 不是 UTF-8 的文件(它是 CP936)。不幸的是,那些对 UTF-8 BOM 造成巨大痛苦负责的人在很大程度上对它视而不见。
7赞 pib 2/9/2010 #4

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

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

评论

2赞 barlop 3/3/2018
你有没有例子,软件根据它编码的先前编码是否具有 BOM,决定是否使用带/不带 BOM 的 UTF-8?!这似乎是一个荒谬的说法
299赞 paercebal 2/9/2010 #5

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

  • 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”

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

编码应该是已知的,而不是占卜的。

评论

72赞 paercebal 9/12/2011
@Alcott:你没看错。字符串 [EF BB BF 41 42 43] 只是一堆字节。您需要外部信息来选择如何解释它。如果您认为这些字节是使用 ISO-8859-1 编码的,则字符串为“ABC”。如果您认为这些字节是使用 UTF-8 编码的,那么它就是“ABC”。如果你不知道,那么你必须试着找出答案。BOM可能是一个线索。解码为 UTF-8 时没有无效字符可能是另一个......最后,除非你能以某种方式记住/找到编码,否则字节数组只是一个字节数组。
24赞 user877329 6/22/2013
@paercebal 虽然“”是有效的拉丁语-1,但文本文件不太可能以该组合开头。这同样适用于 ucs2-le/be 标记 ÿþ 和 þÿ。你也永远不会知道。
17赞 user877329 11/5/2013
@deceze 它可能在语言上无效:首先是 ï(没问题),然后是中间没有空格的引号(不行)。¿ 表示它是西班牙语,但 ï 在西班牙语中不使用。结论:它不是拉丁语-1,其确定性远高于没有它的确定性。
29赞 deceze 11/5/2013
@user 当然,这不一定有意义。但是,如果你的系统依赖于猜测,那就是不确定性的来源。一些恶意用户故意提交以这 3 个字母开头的文本,您的系统突然假设它正在查看带有 BOM 的 UTF-8,将文本视为 UTF-8,它应该使用 Latin-1,并进行一些 Unicode 注入。只是一个假设的例子,但肯定是可能的。你不能通过其内容、句点来判断文本编码。
56赞 jpmc26 7/24/2015
“编码应该是已知的,而不是占卜的。”问题的核心和灵魂。+1,好先生。换句话说:要么标准化你的内容,然后说,“我们一直在使用这种编码。时期。这样写吧。以这种方式阅读“,或开发一种允许将编码存储为元数据的扩展格式。(后者可能也需要一些“引导标准编码”。就像说“告诉你编码的部分始终是 ASCII。
52赞 dan04 8/1/2010 #6

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

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

长答案:

最初,人们期望Unicode将采用UTF-16 / UCS-2编码。BOM 是针对此编码形式设计的。当您有 2 字节代码单元时,必须指示这两个字节的顺序,执行此操作的常见约定是在数据开头包含字符 U+FEFF 作为“字节顺序标记”。字符 U+FFFE 是永久未分配的,因此它的存在可用于检测错误的字节顺序。

无论平台字节序如何,UTF-8 都具有相同的字节顺序,因此不需要字节顺序标记。但是,它可能(作为字节序列)出现在从 UTF-16 转换为 UTF-8 的数据中,或者作为“签名”来指示数据是 UTF-8。EF BB FF

哪个更好?

没有。正如马丁·科特(Martin Cote)所回答的那样,Unicode标准不推荐它。它会导致非 BOM 感知软件出现问题。

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

评论

9赞 endolith 7/15/2012
这也将使带有单个错误字节的有效 UTF-8 无效,尽管 :/
10赞 Cheers and hth. - Alf 6/18/2014
-1 re “它会导致非 BOM 感知软件出现问题”,这对我来说从来都不是问题,但相反,缺少 BOM 会导致 BOM 感知软件(特别是 Visual C++)出现问题。因此,这种说法是非常特定于平台的,是一个狭隘的 Unix 领域观点,但被误导性地呈现为好像它适用于一般情况。但事实并非如此。
6赞 tchrist 10/2/2014
不,UTF-8 没有 BOM。这个答案是不正确的。请参阅 Unicode 标准。
2赞 brighty 2/10/2015
当只看字节时,你甚至可以认为你有一个纯 ASCII 文件。但这也可能是一个 utf-16 文件,您必须在其中查看单词而不是字节。现代软件应该了解 BOM。如果检测到无效序列、可以使用较小序列的代码点或作为代理的代码点,则读取 utf-8 可能会失败。对于 utf-16,当存在孤立的代理项时,读取也可能失败。
3赞 bballdave025 1/18/2020
@Alf,我不同意你对非 BOM 态度的解释,即“特定于平台的、狭隘的 Unix 领域观点”。对我来说,狭隘的思想可能存在于“Unix土地”的唯一方式是MS和Visual C++先于*NIX,但他们没有。MS(我假设是故意的)开始使用 UTF-8 而不是 UTF-16 的 BOM 这一事实向我表明,他们提倡中断、、、和许多其他免费且强大的工具。想让事情正常运转吗?只需购买 MS 版本即可。MS 造成了特定于平台的问题,就像他们的 \x80-\x95 范围的灾难一样。shperlg++
17赞 Halil Özgür 7/11/2011 #7

BOM 倾向于在某个地方、某个地方蓬勃发展(没有双关语(原文如此))。当它蓬勃发展时(例如,浏览器、编辑器等无法识别),它会在文档开头显示为奇怪的字符(例如,HTML 文件、JSON 响应、RSS 等),并导致尴尬,例如最近在奥巴马在 Twitter 上谈论时遇到的编码问题

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

评论

0赞 user984003 2/1/2013
是的,只是花了几个小时来识别由文件编码为 UTF-8 而不是没有 BOM 的 UTF-8 引起的问题。(这个问题只出现在 IE7 中,所以这让我大吃一惊。我使用了 Django 的“include”。
0赞 Halil Özgür 2/1/2013
未来的读者:请注意,我上面提到的推文问题与 BOM 并不严格相关,但如果是,那么推文将以类似的方式出现乱码,但在推文的开头。
15赞 tchrist 10/2/2014
@user984003 不,问题是Microsoft误导了你。它所谓的 UTF-8 不是 UTF-8。它所说的没有 BOM 的 UTF-8 就是 UTF-8 的真正含义。
0赞 JoelFan 10/24/2017
“原文如此”为您的“没有双关语”增加了什么
2赞 Halil Özgür 10/24/2017
@JoelFan 我已经不记得了,但我想这个双关语可能是故意的,尽管作者声称:)
6赞 user1358065 5/11/2012 #8

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

我在我的页面上使用了多种语言(甚至是西里尔文)很长时间了,当文件在没有 BOM 的情况下保存并且我重新打开它们以使用编辑器进行编辑时(正如 cherouvim 也指出的那样),一些字符已损坏。

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

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

评论

4赞 barfuin 5/8/2013
感谢您提供有关 Windows 经典记事本的出色提示。我已经花了一些时间找出完全相同的东西。我的结果是始终使用Notepad ++而不是Windows经典记事本。:-)
0赞 brighty 2/10/2015
你最好使用 madedit。它是唯一一个在十六进制模式下显示一个字符的编辑器,如果您选择 utf-8 字节序列而不是字节和字符之间的 1:1 基数。一个知道UTF-8文件的十六进制编辑器应该像madedit一样!
0赞 barlop 3/3/2018
@brighty 我不认为为了 BOM 而需要一对一。没关系,识别 UTF-8 BOM 是 efbbbf 或 fffe(如果读错了,则为 fffe)并不需要太多。可以简单地删除这些字节。虽然为文件的其余部分提供映射也不错,但也能够逐个字节删除
0赞 brighty 3/5/2018
@barlop 如果文件的内容是 utf-8 编码的,为什么要删除 utf-8 BOM?BOM 被现代文本查看器、文本控件和文本编辑器识别。utf-8 序列的一对一视图是没有意义的,因为 n 个字节会产生一个字符。当然,文本编辑器或十六进制编辑器应该允许删除任何字节,但这可能会导致无效的 utf-8 序列。
0赞 barlop 3/5/2018
@brighty带 BOM 的 UTF-8 是一种编码,不带 BOM 的 UTF-8 是一种编码。cmd 提示符使用不带 bom 的 utf8。因此,如果您有一个 UTF8 文件,请运行 UTF8 支持命令,它是没有 BOM 的 UTF8。如果这样做,则只有在没有 bom 的情况下才会正确显示。如果您执行或将字符输出到文件 a.a,并且您有 chcp 65001,它将不带 BOM 输出。chcp 65001type myfileecho aaa>a.aecho אאא>a.a
37赞 Helen Craigman 6/29/2012 #9

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

如果保存的 CSV 文件没有 BOM,Excel 会认为它是 ANSI 并显示乱码。在前面添加“EF BB BF”后(例如,使用带有 UTF-8 的记事本重新保存它;或使用 UTF-8 的记事本++)重新保存它,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赞 barfuin 5/8/2013
感谢您提供这个出色的提示,以防有人创建供 Excel 使用的 UTF-8 文件。但在其他情况下,我仍然会遵循其他答案并跳过 BOM。
5赞 Roberto Alsina 9/10/2013
如果您创建的文件仅包含 ASCII,并且更高版本可能添加了非 ASCII,则它也很有用。我刚刚遇到了这样的问题:需要 utf8 的软件会创建包含一些数据的文件以供用户编辑。如果初始文件仅包含 ASCII,在某些编辑器中打开然后保存,则它最终以 latin-1 格式结束,并且一切都会中断。如果我添加 BOM,编辑器会将其检测为 UTF8,一切正常。
1赞 kjbartel 1/27/2015
我发现多个与编程相关的工具需要 BOM 正确识别 UTF-8 文件。Visual Studio、SSMS、SoureTree...。
10赞 Deduplicator 8/12/2015
您在哪里阅读有关在该 RFC 中使用 BOM 的建议至多,强烈建议在某些情况下不要禁止它,因为这样做很困难。
15赞 11/26/2016
Excel 认为这是 ANSI 并显示胡言乱语,那么问题出在 Excel 中。
6赞 Florin Sima 9/11/2012 #10

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

但是,当我们在 Windows 或 Linux 上拥有文本、CSV 和 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文件中。

评论

4赞 Functino 11/15/2015
我知道这是一个古老的答案,但我只想提一下,这是错误的。Linux 上的文本文件(不能代表其他 Unix)通常为 /are/ UTF-8。
0赞 bballdave025 11/8/2023
这是支持还是反对 UTF-8 BOM 的答案?我认为这是为了,但我不能确定。
167赞 jpsecher 11/15/2012 #11

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

  1. 不包含文本的文件不再是空的,因为它们始终包含 BOM。
  2. 在 UTF-8 的 ASCII 子集中保存文本的文件本身不再是 ASCII,因为 BOM 不是 ASCII,这使得一些现有工具崩溃,用户可能无法替换此类旧工具。
  3. 无法将多个文件连接在一起,因为每个文件现在的开头都有一个 BOM。

而且,正如其他人所提到的,拥有 BOM 来检测某些东西是 UTF-8 既不充分也不必要:

  • 这还不够,因为任意字节序列可能恰好以构成 BOM 的确切序列开头。
  • 这不是必需的,因为您可以像读取 UTF-8 一样读取字节;如果成功,根据定义,它是有效的 UTF-8。

评论

12赞 Cheers and hth. - Alf 6/18/2014
关于第 1 点“不包含文本的文件不再是空的,因为它们始终包含 BOM”,这 (1) 将操作系统文件系统级别与解释的内容级别混为一谈,并且它 (2) 错误地假设使用 BOM 必须将 BOM 也放在每个原本是空的文件中。(1)的实际解决方案是不做(2)。从本质上讲,投诉简化为“有可能不切实际地将 BOM 放入原本是空的文件中,从而阻止最容易检测到逻辑上空的文件(通过检查文件大小)”。尽管如此,好的软件应该能够处理它,因为它是有目的的。
10赞 Cheers and hth. - Alf 6/18/2014
第 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 字节值进行细分的工具。一个可能更好的解决方案是抛弃那些不好的工具。
9赞 Cheers and hth. - Alf 6/18/2014
关于第 3 点,“不可能将多个文件连接在一起,因为每个文件现在开头都有一个 BOM”是错误的。我将 UTF-8 文件与 BOM 连接起来没有问题,所以这显然是可能的。我想也许你的意思是 Unix-land 不会给你一个干净的结果,一个只在一开始就有 BOM 的结果。如果你是这个意思,那是因为在字节级别工作,而不是在解释内容级别工作,并且以类似的方式无法处理照片,比如说。尽管如此,它并没有造成太大的伤害。这是因为 BOM 对零宽度的不间断空格进行编码。catcatcat
32赞 tchrist 10/2/2014
@Cheersandhth.-阿尔夫 这个答案是正确的。您只是在指出Microsoft的错误。
14赞 Deduplicator 9/20/2015
@brighty:不过,添加 bom 并没有改善这种情况。
-5赞 user2173444 3/15/2013 #12

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

这是我的观点(30 年的计算和 IT 行业)。

评论

1赞 asontu 11/28/2017
我发现这也是真的。如果您使用前 255 个 ASCII 集之外的字符并省略 BOM,浏览器会将其解释为 ISO-8859-1,并且您会得到乱码。鉴于上面的答案,这显然是浏览器供应商在未检测到 BOM 时做错了事情。但是,除非您在Microsoft Edge / Mozilla / Webkit / Blink工作,否则您别无选择,只能使用这些应用程序的缺陷。
1赞 Peter Mortensen 4/17/2020
UTF是什么?UTF-8?UTF-16?别的?
1赞 Jasen 8/9/2020
如果您的服务器没有输入正确的 mime 类型字符集参数,则应在 HTML 标头中使用该标记。<meta http-equiv
4赞 Marek Möhling 6/22/2013 #13

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

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

另外,我刚刚在维基百科上找到了这个:

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

6赞 David 1/25/2014 #14

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

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

为了响应 shebang 行指定您希望使用的 shell:

#!/bin/bash

如果您另存为 UTF-8,则没有 BOM(例如在 BBEdit 中)一切都会很好。

评论

11赞 tchrist 10/2/2014
这是因为Microsoft已经交换了标准所说的含义。UTF-8 没有 BOM:他们创建了 Microsoft UTF-8,它在数据流前面插入了一个虚假的 BOM,然后告诉你不,这实际上是 UTF-8。事实并非如此。它只是在扩展和破坏。
7赞 James Wakefield 7/3/2014 #15

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

我想明确表示,我宁愿根本没有 BOM。如果一些旧的垃圾没有它,就会添加它,并且替换该旧应用程序是不可行的。

不要期望 UTF-8 的 BOM。

评论

1赞 Jasen 8/9/2020
如果非 UTF8 感知应用程序遇到 UTF8,它们不确定它们是否会失败,UTF8 的全部意义在于,许多事情都会正常工作,会给出正确的行数和八位字节数,以及正确的字数,如果不使用仅 Unicode 的间距字符。wc(1)
0赞 James Wakefield 12/16/2021
我同意你@Jasen的看法。如果我只是删除这个旧答案,请尝试锻炼。我目前的观点是,答案是根本不添加 BOM。如果最终用户必须破解文件以使其与旧软件一起使用,则可以附加一个。我们不应该制造使这种错误行为永久化的软件。没有理由不能以零宽度非联接器开头,而零宽度非联接器应被解释为零宽度非联接器。
18赞 DavidRR 10/3/2014 #16

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

以下是维基百科上关于字节顺序标记 (BOM) 的文章的一些摘录,我相信它们为这个问题提供了可靠的答案。

关于 BOM 和 UTF-8 的含义:

Unicode 标准允许 UTF-8 格式的 BOM,但不要求 或推荐使用它。字节顺序在 UTF-8 中没有意义,因此其 在 UTF-8 中的唯一用途是在开始时发出文本流是 以 UTF-8 编码。

使用 BOM 的参数

不使用 BOM 的主要动机是向后兼容性 使用无法识别 Unicode 的软件...不的另一个动机 使用 BOM 是为了鼓励使用 UTF-8 作为“默认”编码。

使用 BOM 参数

使用 BOM 的论点是,没有它,启发式分析是 需要确定文件使用的字符编码。 从历史上看,为了区分各种 8 位编码,这种分析是 复杂,容易出错,有时速度慢。多个库 可用于简化任务,例如 Mozilla Universal Charset Unicode 的检测器和国际组件。

程序员错误地认为 UTF-8 的检测是平等的 困难(这不是因为绝大多数字节序列 是无效的 UTF-8,而这些库正在尝试的编码 区分允许所有可能的字节序列)。因此不是全部 Unicode 感知程序执行此类分析,而是依赖于 BOM。

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

在哪个更好,没有 BOM:

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

我的结论:

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

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


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

评论

5赞 eQ19 4/16/2015
我最好严格要求没有 BOM。我发现,结合 UTF-8 BOM 给出编码错误,更改为没有 BOM 的 UTF-8 编码,按照此处解释的建议解决问题.htaccessgzip compression
1赞 Sz. 3/15/2018
“不使用 BOM 的另一个动机是鼓励将 UTF-8 作为”默认“编码。--这是一个如此强大和有效的论点,你实际上可以在那里停止答案... ;-o除非你对通用文本表示有更好的想法,否则就是这样。;)(我不知道你多大了,在UTF8之前的时代,你经历了多少年的痛苦(当时语言学家们拼命考虑改变他们的字母表),但我可以告诉你,每一秒,我们都更接近于摆脱所有古老的单字节无元数据编码的混乱,而不是拥有“唯一”是纯粹的快乐。
0赞 Sz. 3/15/2018
另请参阅此评论,了解将 BOM(或任何东西)添加到最简单的文本文件格式“纯文本”中,这意味着如何防止最佳通用文本编码格式成为“纯文本”和“简单”(即“无顶”)...
0赞 Eric Grange 8/23/2019
BOM 在 Linux 上主要是有问题的,因为许多实用程序一开始并不真正支持 Unicode(例如,它们很乐意在代码点中间截断)。对于大多数其他现代软件环境,只要编码不明确(通过规范或元数据),就使用 BOM。
8赞 Wernfried Domscheit 2/1/2015 #17

应该注意的是,对于某些文件,即使在 Windows 上也不得拥有 BOM。例如,或文件。如果此类文件包含 BOM,则在尝试执行它们时会出现错误。SQL*plusVBScript

17赞 jpc-ae 1/26/2016 #18

这个问题已经有一百零一个答案,其中许多都非常好,但我想尝试澄清何时应该或不应该使用 BOM。

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

如果找到与 UTF-8 BOM 对应的字节码,则概率足够高,可以假设它是 UTF-8,您可以从那里开始。然而,当被迫做出这种猜测时,在阅读时进行额外的错误检查仍然是一个好主意,以防出现乱码。如果输入绝对不应该是 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 上尤其如此,因为没有 BOM 的任何内容通常都假定使用旧代码页。BOM 告诉 Office 等程序,是的,此文件中的文本是 Unicode;下面是使用的编码。

归根结底,我唯一真正有问题的文件是 CSV。根据程序的不同,它必须或不得具有 BOM。例如,如果您在 Windows 上使用 Excel 2007+,则必须使用 BOM 对其进行编码,以便顺利打开它而不必求助于导入数据。

评论

10赞 rmunn 8/23/2019
您答案的最后一部分是 100% 正确的:使用 BOM 的唯一原因是您必须与不使用 UTF-8 作为默认解析未知文件的错误软件进行互操作。
138赞 rsp 6/26/2016 #19

以下是实际导致实际问题的 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,通常用于 当前类 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 在前四个字节中只有一个 NULL,因此无法识别
  4. UTF-16LE 在前四个字节中只有一个 NULL,因此无法识别

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

此外,如果实现测试了我建议的有效 JSON,它甚至会拒绝确实编码为 UTF-8 的输入,因为它不会像 RFC 那样以 ASCII 字符< 128 开头。

其他数据格式

不需要 JSON 中的 BOM,这是非法的,并且会破坏根据 RFC 正常工作的软件。当时不使用它应该是不费吹灰之力的,但是,总有人坚持使用 BOM、注释、不同的引用规则或不同的数据类型来破坏 JSON。当然,如果你需要的话,任何人都可以自由地使用BOM或其他任何东西--只是不要称它为JSON。

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

BOM的其他用途

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

评论

7赞 Eric Grange 4/10/2017
取代 RFC4627 的 RFC7159 实际上表明支持 BOM 可能并不那么邪恶。基本上,没有 BOM 只是一个模棱两可的 kludge,因此无法识别 Unicode 的旧 Windows 和 Unix 软件仍然可以处理 utf-8。
23赞 Sz. 3/15/2018
@EricGrange,您似乎非常支持 BOM,但没有意识到这将使无处不在、普遍有用、最佳最小值的“纯文本”格式成为 UTF8 之前的遗物!根据定义,向文本流添加任何类型的(带内)标头都会对最简单的文本文件施加强制性协议,使其不再是“最简单”的!为了什么收益?为了支持所有其他没有签名的古老 CP 编码,您可能会将它们误认为是 UTF-8?(顺便说一句,ASCII 也是 UTF-8。那么,这些 BOM 也是如此吗?;)来吧。
5赞 Tono Nam 7/2/2019
这个答案就是我提出这个问题的原因!我在 Windows 中创建我的 bash 脚本,在将这些脚本发布到 Linux 时遇到了很多问题!杰森文件也是如此。
5赞 rmunn 8/23/2019
我希望我能把这个答案投五十次左右。我还想补充一点,在这一点上,UTF-8 已经赢得了标准战争,几乎所有在互联网上产生的文本都是 UTF-8。一些最流行的编程语言(如 C# 和 Java)在内部使用 UTF-16,但当使用这些语言的程序员将文件写入输出流时,他们几乎总是将它们编码为 UTF-8。因此,使用 BOM 来标记 UTF-8 文件不再有意义;UTF-8 应该是您在读取时使用的默认值,并且仅在 UTF-8 解码失败时尝试其他编码。
4赞 rmunn 8/23/2019
@EricGrange - 真的吗?快速的谷歌搜索表明与我相反:stackoverflow.com/questions/2905582/...是关于UTF-8 BOM如何在Eclipse中显示为一个字符(即,Eclipse认为那里不应该有BOM,并且不知道如何处理它),dzone.com/articles/what-does-utf-8-bom-mean 说“在Eclipse中,如果我们使用UTF-8设置默认编码,它将使用没有字节顺序标记(BOM)的普通UTF-8”。当省略 UTF-8 BOM 时,人们正在讨论 Eclipse 失败的地方有什么链接吗?
5赞 Wernfried Domscheit 3/8/2018 #20

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 big-endian 或 Unicode little-endian),则不应使用 BOM。在 特别是,每当数据流被声明为 UTF-16BE, 不得使用 UTF-16LE、UTF-32BE 或 UTF-32LE 物料清单。

1赞 Leo 7/31/2019 #21

以下是我在 Visual Studio、Sourcetree 和 Bitbucket 拉取请求方面的经验,这给我带来了一些问题:

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

Enter image description here

如果你将鼠标悬停在它上面,它会显示一个像“ufeff”这样的字符,但事实证明 Sourcetree 不显示这些类型的字节标记,所以它很可能会出现在你的拉取请求中,这应该没问题,因为这就是 Visual Studio 2017 现在编码新文件的方式,所以也许 Bitbucket 应该忽略这一点或让它以另一种方式显示, 更多信息在这里:

红点标记 BitBucket 差异视图

1赞 Good Pen 5/8/2022 #22

我用utf-8保存了一个自动热键文件,汉字变成了strrang。

使用 utf-8 BOM,工作正常。

AutoHotkey 不会自动识别 UTF-8 文件,除非它以字节顺序标记开头。

https://www.autohotkey.com/docs/FAQ.htm#nonascii