UTF-8和UTF-8与BOM有什么不同?哪个更好?
当前回答
以下是我使用Visual Studio、Sourcetree和Bitbucket拉请求的经验,这给了我一些问题:
因此,在审查拉取请求时,带有签名的BOM将在每个文件上包含一个红点字符(这可能非常烦人)。
如果你把鼠标停在上面,它会显示一个像“ufeff”这样的字符,但事实证明Sourcetree不显示这些类型的字节标记,所以它很可能会在你的拉请求中结束,这应该是可以的,因为这是Visual Studio 2017现在编码新文件的方式,所以也许Bitbucket应该忽略这个或让它以另一种方式显示,更多信息在这里:
红点标记BitBucket差异视图
其他回答
当您希望显示以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文件中。
我从另一个角度看这个问题。我认为UTF-8与BOM更好,因为它提供了更多关于文件的信息。我只在遇到问题时才使用没有BOM的UTF-8。
我在我的页面上使用多种语言(甚至西里尔字母)很长一段时间,当文件保存时没有BOM,我重新打开它们用编辑器编辑(cherouvim也指出),一些字符被损坏了。
请注意,当您尝试以UTF-8编码保存新创建的文件时,Windows的经典记事本会自动保存带有BOM的文件。
我个人保存带有BOM的服务器端脚本文件(.asp, .ini, .aspx)和没有BOM的.html文件。
引用于维基百科页面底部BOM: http://en.wikipedia.org/wiki/Byte-order_mark#cite_note-2
对于UTF-8,使用BOM既不要求也不推荐,但在从使用BOM的其他编码形式转换UTF-8数据或将BOM用作UTF-8签名的上下文中可能会遇到这种情况。
下面是一些实际导致问题的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,章节:魔法数字:
The shebang characters are represented by the same two bytes in extended ASCII encodings, including UTF-8, which is commonly used for scripts and other text files on current Unix-like systems. However, UTF-8 files may begin with the optional byte order mark (BOM); if the "exec" function specifically detects the bytes 0x23 and 0x21, then the presence of the BOM (0xEF 0xBB 0xBF) before the shebang will prevent the script interpreter from being executed. Some authorities recommend against using the byte order mark in POSIX (Unix-like) scripts,[14] for this reason and for wider interoperability and philosophical concerns. Additionally, a byte order mark is not necessary in UTF-8, as that encoding does not have endianness issues; it serves only to identify the encoding as UTF-8. [emphasis added]
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
注意:
UTF-32BE不是以三个null开头的,所以它不会被识别 UTF-32LE第一个字节后面没有三个null,所以它不会被识别 UTF-16BE在前四个字节中只有一个NUL,所以它不会被识别 UTF-16LE在前四个字节中只有一个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字符导致实际问题的一个例子。
Unicode字节顺序标记(BOM)常见问题解答提供了一个简明的答案:
Q: How I should deal with BOMs? A: Here are some guidelines to follow: A particular protocol (e.g. Microsoft conventions for .txt files) may require use of the BOM on certain Unicode data streams, such as files. When you need to conform to such a protocol, use a BOM. Some protocols allow optional BOMs in the case of untagged text. In those cases, Where a text data stream is known to be plain text, but of unknown encoding, BOM can be used as a signature. If there is no BOM, the encoding could be anything. Where a text data stream is known to be plain Unicode text (but not which endian), then BOM can be used as a signature. If there is no BOM, the text should be interpreted as big-endian. Some byte oriented protocols expect ASCII characters at the beginning of a file. If UTF-8 is used with these protocols, use of the BOM as encoding form signature should be avoided. Where the precise type of the data stream is known (e.g. Unicode big-endian or Unicode little-endian), the BOM should not be used. In particular, whenever a data stream is declared to be UTF-16BE, UTF-16LE, UTF-32BE or UTF-32LE a BOM must not be used.
推荐文章
- Java标识符中的“连接字符”是什么?
- 使用Javascript的atob解码base64不能正确解码utf-8字符串
- 为什么字符集名称不是常量?
- 编码字符串为UTF-8
- 有没有统一码符号来表示"搜索"
- 我如何在PHP中输出一个UTF-8 CSV, Excel将正确读取?
- Python __str__与__unicode__
- 如何在Python中将字符串转换为utf-8
- Unicode和UTF-8的区别是什么?
- 我真的需要将“&”编码为“&”吗?
- 用Python写入UTF-8文件
- c++中的_tmain()和main()有什么区别?
- HTML编码问题-显示“”字符而不是“ ”
- 将Unicode文本写入文本文件?
- PHP DOMDocument loadHTML没有正确编码UTF-8