没有BOM的 UTF-8和UTF-8有什么区别?哪个更好?
没有BOM的 UTF-8和UTF-8有什么区别?哪个更好?
Answers:
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节 “ 特价 ”中的“字节顺序标记”小节。
其他出色的答案已经回答:
EF BB BF
但是,作为对此的附加信息,如果字符串以UTF-8编码,则UTF-8的BOM可能是“嗅觉”的好方法...或者它可以是任何其他编码形式的合法字符串...
例如,数据[EF BB BF 41 42 43]可以是:
因此,虽然通过查看第一个字节来识别文件内容的编码可能很酷,但您不应依赖它,如上面的示例所示
编码应该是已知的,而不是不可分割的。
将BOM放入UTF-8编码的文件中至少存在三个问题。
而且,正如其他人提到的那样,拥有BOM表来检测某物是否为UTF-8既不充分,也没有必要:
cat
不会给您一个干净的结果,这个结果仅在开始时才包含BOM。如果您这样说,那是因为cat
在字节级别上工作,而不是在解释的内容级别上工作,并且以类似的方式cat
不能处理照片。仍然没有太大的伤害。这是因为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。[重点添加]
实现不得在JSON文本的开头添加字节顺序标记。
不仅在JSON中是非法的,而且不需要确定字符编码,因为存在更可靠的方法来明确确定任何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
注意:
根据实现的不同,所有这些都可能被错误地解释为UTF-8,然后被错误地解释或拒绝为无效的UTF-8,或者根本无法被识别。
此外,如果实现按照我的建议测试有效的JSON,那么即使该输入确实被编码为UTF-8,它也会拒绝输入,因为它的开头不是ASCII字符<128,这与RFC所要求的相同。
不需要JSON中的BOM,这是非法的,并且会破坏根据RFC正常运行的软件。那时不使用它应该是一个明智的选择,但是总有些人坚持通过使用BOM,注释,不同的引用规则或不同的数据类型来破坏JSON。当然,任何人都可以自由使用BOM或其他任何需要的东西-那就不要将其称为JSON。
对于除JSON之外的其他数据格式,请看一下它的真正外观。如果唯一的编码是UTF- *,并且第一个字符必须是小于128的ASCII字符,那么您已经具有确定数据的编码和字节序所需的所有信息。即使将BOM表作为可选功能添加,也只会使其更加复杂且容易出错。
至于JSON或脚本之外的用途,我认为这里已经有很好的答案。我想添加有关脚本和序列化的更详细的信息,因为这是导致实际问题的BOM字符的示例。
没有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,则可能是这样。
sh
,perl
,g++
,和其他许多自由和强大的工具。想要工作吗?只需购买 MS版本。MS产生了特定于平台的问题,就像\ x80- \ x95范围的灾难一样。
具有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)
BOM倾向于在某处某处繁荣(没有双关语)。而且当它蓬勃发展时(例如,未被浏览器,编辑器等识别),它会
在文档开始时显示为奇怪的字符(例如,HTML文件,JSON响应,RSS等)。并导致这种尴尬,如奥巴马在Twitter上的谈话中最近遇到的编码问题。
当它出现在难以调试的地方或忽略测试时,这很烦人。因此,除非您必须使用它,否则最好避免使用它。
问题:没有BOM的UTF-8和UTF-8有什么区别?哪个更好?
这是Wikipedia文章中有关字节顺序标记(BOM)的一些摘录,我相信这些摘录可为该问题提供可靠的答案。
关于BOM和UTF-8的含义:
Unicode标准允许BOM的UTF-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 †一起使用时,诸如type
和more
不希望BOM存在的命令。如果BOM 是本,它可以是有问题的,因为它是用于其他应用。
这个问题已经有一百万个答案了,其中许多都很好,但是我想尝试弄清楚何时应该使用或不应该使用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一样使用程序,则应使用BOM进行编码。在Windows上尤其如此,在Windows上,通常假定没有BOM的任何东西都在使用旧版代码页。BOM告诉Office之类的程序,是的,该文件中的文本为Unicode。这是使用的编码。
说到它,我真正真正遇到过的唯一文件是CSV。根据程序,它要么必须具有BOM,要么必须没有BOM。例如,如果您在Windows上使用Excel 2007+,则要平滑打开它而不必求助于导入数据,则必须使用BOM对其进行编码。
请注意,对于某些文件,即使在Windows上也必须没有 BOM。示例是SQL*plus
或VBScript
文件。如果此类文件包含BOM表,则在尝试执行它们时会出错。
在BOM表的Wikipedia页面底部引用:http : //en.wikipedia.org/wiki/Byte-order_mark#cite_note-2
“对于UTF-8,既不需要也不建议使用BOM,但是在从使用BOM的其他编码形式转换UTF-8数据或BOM用作UTF-8签名的情况下,可能会遇到BOM的情况。”
没有BOM的UTF-8没有BOM,这不会比带有BOM的UTF-8更好,除非文件的使用者需要知道(或会从中获知)文件是否为UTF-8编码或不。
BOM通常可用于确定编码的字节序,这在大多数情况下不是必需的。
此外,对于那些不了解或不关心BOM的用户而言,BOM可能是不必要的噪音/痛苦,并可能导致用户困惑。
我从另一个角度看待这个问题。我认为带有BOM的UTF-8更好,因为它提供了有关文件的更多信息。仅当遇到问题时,我才使用不带BOM的UTF-8。
我长时间在页面上使用多种语言(甚至是西里尔字母),并且保存文件时没有使用BOM,然后重新打开文件以使用编辑器进行编辑(如cherouvim所述),某些字符已损坏。
请注意,Windows的经典记事本当您尝试使用UTF-8编码保存新创建的文件时自动使用BOM表保存文件。
我个人保存带有BOM的服务器端脚本文件(.asp,.ini,.aspx)和不带有BOM的.html文件。
chcp 65001
以获取utf8支持,它是不带bom的utf8。如果这样做type myfile
,则只有在没有Bom的情况下,它才能正确显示。如果执行此操作echo aaa>a.a
或echo אאא>a.a
将字符输出到文件aa,并且具有chcp 65001,则它将输出而没有BOM。
当您要显示以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文件中。
一个实际的区别是,如果您为Mac OS X编写了一个shell脚本并将其另存为普通UTF-8,则将得到响应:
#!/bin/bash: No such file or directory
响应shebang行,指定要使用的外壳:
#!/bin/bash
如果另存为UTF-8,那么所有BOM(例如BBEdit中的内容)都不会很好。
如上所述,带有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]并出于更广泛的互操作性和哲学考虑
Unicode 字节顺序标记(BOM)常见问题解答提供了一个简洁的答案:
问:我应该如何处理BOM?
答:以下是一些指导原则:
特定协议(例如,Microsoft .txt文件约定)可能要求在某些Unicode数据流(例如文件)上使用BOM。当您需要遵循此类协议时,请使用BOM。
对于未加标签的文本,某些协议允许使用可选的BOM。在那种情况下
如果已知文本数据流是纯文本,但编码方式未知,则BOM可用作签名。如果没有BOM,则编码可以是任何形式。
如果已知文本数据流是纯Unicode文本(而不是哪个字节序),则BOM可用作签名。如果没有BOM,则文本应解释为big-endian。
某些面向字节的协议期望在文件开头使用ASCII字符。如果这些协议使用UTF-8,则应避免使用BOM作为编码形式签名。
在已知数据流的确切类型的地方(例如Unicode大端或Unicode小端),不应使用BOM。特别是,无论何时将数据流声明为UTF-16BE,UTF-16LE,UTF-32BE或UTF-32LE,都不得使用BOM。
从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,这会在以后的开发链中引起其他问题。
这是我对Visual Studio,Sourcetree和Bitbucket拉取请求的经验,这给了我一些问题:
因此事实证明,在审查拉动请求时,带有签名的BOM将在每个文件上包含一个红点字符(可能会很烦人)。
如果将鼠标悬停在它上面,它将显示类似“ ufeff”的字符,但事实证明Sourcetree不显示这些类型的字节标记,因此它很可能最终出现在您的请求中,这应该没问题,因为这就是Visual Studio的方式2017现在对新文件进行编码,因此Bitbucket可能会忽略此文件或以其他方式显示它,更多信息请参见:
如果在HTML文件中使用UTF-8,并且在同一页面上使用塞尔维亚西里尔字母,塞尔维亚拉丁字母,德语,匈牙利语或某些外来语言,则带有BOM的UTF更好。
我的观点是(计算机和IT行业已有30年的历史)。