UTF-8 和没有 UTF-8 有什么区别 物料清单?哪个更好?

有帮助吗?

解决方案

在UTF-8 BOM是一个字节在一个文本流(EF BB BF),其允许读者更可靠地猜测一个文件作为以UTF-8正被编码的开始的序列。

通常,BOM被用于信号的编码的字节序,但由于字节序是无关的UTF-8,BOM是不必要的。

按照 Unicode标准 - 用于在 BOM不推荐UTF-8文件

  

2.6编码方案

     

...既不需要一个BOM的用途,也没有建议使用UTF-8,但也可以是   在上下文中,其中UTF-8的数据从其它转化遇到   使用一个BOM或其中BOM被用作UTF-8编码的形式   签名。请参阅的“字节顺序标记”小节的第16.8节,   特别 ,   获得更多信息。

其他提示

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

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

但是,作为附加信息,UTF-8 的 BOM 可能是“嗅出”字符串是否以 UTF-8 编码的好方法...或者它可能是任何其他编码的合法字符串......

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

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

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

编码应该是已知的,而不是猜测的。

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

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

而且,正如其他人提到的,使用 BOM 来检测某些内容是 UTF-8 既不充分也没有必要:

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

这是一个老问题,有很多好的答案,但应该补充一件事。

所有答案都很笼统。我想补充的是 BOM 用法的示例,这些示例实际上会导致真正的问题,但许多人并不了解它。

BOM 破坏脚本

Shell 脚本、Perl 脚本、Python 脚本、Ruby 脚本、Node.js 脚本或任何其他需要由解释器运行的可执行文件 - 全部以 舍邦线 看起来像其中之一:

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

它告诉系统调用此类脚本时需要运行哪个解释器。如果脚本以 UTF-8 编码,人们可能会想在开头包含 BOM。但是实际上是“#!”字符不仅仅是字符。他们其实是一个 幻数 它恰好由两个 ASCII 字符组成。如果您在这些字符之前放置某些内容(例如 BOM),那么该文件将看起来像是具有不同的幻数,这可能会导致问题。

参见维基百科, 文章:舍邦,部分:幻数:

Shebang字符在包括UTF-8的扩展ASCII编码中以相同的两个字节表示,UTF-8(通常用于当前UNIX式系统上的脚本和其他文本文件)。但是,UTF-8文件可以从可选的字节订单标记(BOM)开始;如果“ exec”函数专门检测到字节0x23和0x21,则 在Shebang将阻止脚本解释器被执行之前,BOM的存在(0xef 0xbb 0xbf)。 一些当局建议不要在POSIX(Unix-ligh)脚本中使用字节订单标记,[14]出于这个原因以及更广泛的互操作性和哲学问题。此外,在UTF-8中不需要字节订单标记,因为该编码没有Endianness问题;它仅用于将编码标识为UTF-8。[已添加强调]

JSON 中的 BOM 不合法

RFC 7159,第 8.1 节:

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

JSON中的BOM是多余的

不仅如此 非法的 在 JSON 中,它也是 不需要 确定字符编码,因为有更可靠的方法可以明确确定任何 JSON 流中使用的字符编码和字节顺序(请参阅 这个答案 了解详情)。

BOM 破坏 JSON 解析器

不仅如此 非法的 在 JSON 中和 不需要, ,实际上 破坏所有软件 使用中提出的方法确定编码 RFC 4627:

确定 JSON 的编码和字节顺序,检查前 4 个字节中是否有 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 第一个字节后面没有 3 个 NUL,因此不会被识别
  3. UTF-16BE 前 4 个字节只有 1 个 NUL,因此无法识别
  4. UTF-16LE 前 4 个字节只有 1 个 NUL,因此无法识别

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

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

其他数据格式

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

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

BOM的其他用途

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

  

无BOM什么是UTF-8和UTF-8之间的不同?

短的答案:在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。

  

哪个更好?

无。正如马丁科特回答,Unicode标准不推荐它。它会导致与非BOM感知软件的问题。

一个更好的方法,以检测文件是否是UTF-8是执行有效性检查。 UTF-8有着严格的规定什么字节序列是有效的,那么假阳性的概率可以忽略不计。如果一个字节序列看起来像UTF-8,它可能是。

带 BOM 的 UTF-8 更好识别。我是经过艰难的过程才得出这个结论的。我正在开展一个项目,其结果之一是 CSV 文件,包括 Unicode 字符。

如果保存的 CSV 文件没有 BOM,Excel 会认为它是 ANSI 并显示乱码。一旦你在前面添加“EF BB BF”(例如,使用记事本以UTF-8重新保存它;或 Notepad++ with UTF-8 with BOM),Excel 可以正常打开它。

RFC 3629 建议在 Unicode 文本文件中添加 BOM 字符:“ 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 奥巴马的通话。

这是非常恼人的,当它在地方很难显示出来调试或测试时被忽略。所以,最好是避免它,除非你必须使用它。

问题: UTF-8 和无 BOM 的 UTF-8 有什么不同?哪个更好?

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

关于BOM和UTF-8的含义:

Unicode 标准允许 物料清单UTF-8, ,但不需要或建议其使用。字节顺序在UTF-8中没有含义,因此在UTF-8中唯一使用的是在开始时发出信号,表明文本流是在UTF-8中编码的。

论证 不是 使用物料清单:

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

争论 为了 使用物料清单:

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

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

尤其, 微软 编译器和口译器以及Microsoft Windows上的许多软件(例如Notepad 8。当将Microsoft Word文档下载为纯文本文件时,Google文档将添加BOM。

哪个比较好, 或者 没有 物料清单:

互联网工程任务组 建议如果协议(a)始终使用UTF-8,或者(b)有其他方法来指示正在使用的编码,则“应该禁止使用U+FEFF作为签名”。

我的结论:

使用物料清单 仅有的 如果与软件应用程序的兼容性是绝对必要的。

另请注意,虽然引用的维基百科文章表明许多 Microsoft 应用程序依赖 BOM 来正确检测 UTF-8,但情况并非如此 全部 微软应用程序。例如,正如所指出的 @巴洛普, ,使用带有 UTF-8 的 Windows 命令提示符时, ,命令这样的 typemore 不要期望 BOM 存在。如果物料清单 目前,它可能会像其他应用程序一样出现问题。


† 这 chcp 命令提供对 UTF-8 的支持(没有 BOM)通过代码页 65001.

在上BOM维基百科页面底部引用: HTTP:// EN .wikipedia.org /维基/字节order_mark#cite_note-2

  

“物料清单既不要求也不建议对于UTF-8,但也可以在上下文其中UTF-8的数据从使用一个BOM或其中BOM被用作UTF-8其他编码形式转换遇到的使用签名“

应该指出的是,对于某些文件您不可以有BOM甚至在Windows上。例子是SQL*plusVBScript文件。如果这些文件包含一个BOM,当您尝试执行他们,你得到一个错误。

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

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

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

为什么不建议使用 BOM?

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

什么时候 应该 你用BOM编码吗?

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

归根结底,我唯一真正遇到问题的文件是 CSV。根据程序的不同,它要么必须有 BOM,要么不能没有 BOM。例如,如果您在 Windows 上使用 Excel 2007+,如果您想顺利打开它而不需要导入数据,则必须使用 BOM 对其进行编码。

UTF-8与BOM仅帮助,如果该文件实际上包含一些非ASCII字符。如果包括在内,没有任何的话,那很可能会打破,将有其解释文件为纯ASCII旧的应用程序。当他们遇到非ASCII字符,所以在我看来应该只添加BOM时,该文件就可以了,应该不再被理解为纯ASCII这些应用程序肯定会失败。

编辑:只想说清楚,我宁愿没有BOM可言,如果在使用了它,并取代这一传统应用程序的一些老垃圾断裂是不可行的添加它

不要让任何期待的UTF8 BOM。

UTF-8无BOM没有BOM,这并不能使它优于UTF-8 BOM,当文件的消费者需要知道,除了该文件是(或将从中受益知道),UTF- 8编码的或不

在BOM通常是有用的,以确定编码,这是不需要的大多数使用情况的字节序。

此外,BOM可以为那些消费者不知道或不关心它不必要的噪音/疼痛,并可能导致用户混淆。

我看这从不同的角度。我想的 UTF-8与BOM是更好,因为它提供了有关该文件的更多信息。我使用UTF-8无BOM只有当我面临的问题。

我使用多国语言(甚至西里尔)我的网页上很长一段时间,当文件被保存而不BOM和我重新打开他们用编辑器编辑(如 cherouvim 也注意到),一些字符被损坏。

需要注意的是Windows的经典记事本自动保存文件当您尝试使用UTF-8编码新创建的文件中的BOM。

我个人保存服务器侧的脚本文件(的.asp,的.ini,的.aspx)与BOM 和<强> .html文件无BOM

当要显示在UTF-8可能不面对的问题编码的信息。声明例如HTML文档为UTF-8,你会在浏览器中显示的所有包含在文档的身体。

但是,当我们有文字, CSV 和XML文件不是这种情况,无论是在Windows或Linux。

例如,在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 )都将是好。

如上所述,UTF-8与BOM可能导致与非BOM感知(或兼容)软件问题。我曾经编辑后的编码为UTF-8 + BOM与基于Mozilla的 KompoZer会 HTML文件,作为一个需要客户端 WYSIWYG 计划。

不约而同保存时的布局将被摧毁。它花了我一些时间来摆弄我身边这样。然后,这些文件在Firefox中运作良好,但显示在Internet Explorer中的CSS怪癖破坏布局,再一次。与小时无果链接的CSS文件摆弄之后,我发现,Internet Explorer中不喜欢BOMfed HTML文件。不会再

另外,我刚发现这在维基百科:

  

在认领字符在扩展ASCII编码,包括UTF-8,其通常用于在当前类Unix系统脚本和其他的文本文件的相同的两个字节表示。然而,UTF-8的文件可以与可选的字节顺序标记(BOM)开始;如果“EXEC”的功能特异性检测的认领将防止脚本解释器被执行前的字节0×23 0×21,则该BOM(0xEF为0xBB为0xBF)的存在下进行。一些权威人士建议针对在POSIX(UNIX类)脚本使用字节顺序标记,[15]由于这个原因和更广泛的互操作性和哲学关注

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

问:我应该如何处理 BOM?

A:以下是一些需要遵循的准则:

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

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

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

    • 如果已知文本数据流是纯 Unicode 文本(但不知道哪种字节序),则可以使用 BOM 作为签名。如果没有BOM,则应将文本解释为大型。

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

  4. 数据流的精确类型已知(例如Unicode big-endian 或 Unicode Little-endian),不应使用 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和到位桶拉请求,这已经给了我一些问题的经验:

所以原来BOM用签名将包括在每个文件中的红点字符审查pull请求时(可能是非常令人讨厌)。

“在这里输入的图像描述”

如果您将鼠标悬停在上面,它会显示类似“ufeff”角色,但事实证明sourcetree并不表明这些类型的bytemarks的,所以它很可能会最终在你拉的请求,这应该是OK的,因为这是怎么2017年VS编码新文件现在,所以也许应该到位桶这里忽略这或使其表现出另一种方式,更多的信息:

红点标记到位桶的diff视图

UTF与BOM是更好,如果你在HTML文件中使用UTF-8,如果你使用塞尔维亚西里尔文塞尔维亚拉丁语,在同一个页面德语,匈牙利语什么奇特的语言。这是我的意见(30岁计算和IT产业的)。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top