4 回答
TA贡献1839条经验 获得超15个赞
UTF-8 BOM是文本流(EF BB BF)开始时的字节序列,它允许读者更可靠地猜测文件是在UTF-8中编码的。
通常,BOM用来表示编码的endianness,但是由于endianness与UTF-8无关,所以BOM是不必要的。
TA贡献1859条经验 获得超6个赞
UTF-8和BOM-ed UTF-8之间没有正式区别。 BOM编辑的UTF-8字符串将以下三个字节开始. EF BB BF
如果存在这些字节,则在从文件/流中提取字符串时必须忽略这些字节。
合法 字符串“ain”、“abc” 合法 字符串“abc”
编码应该是已知的,而不是预言。
TA贡献1998条经验 获得超6个赞
不包含文本的文件不再是空的,因为它们总是包含BOM。 在UTF-8的ASCII子集中保存文本的文件不再是ASCII,因为BOM不是ASCII,这使得一些现有工具崩溃,用户可能无法替换这些遗留工具。 不可能将多个文件连接在一起,因为现在每个文件在开始时都有一个BOM。
这是不够的,因为任意字节序列可能会以构成BOM的确切序列开始。 没有必要,因为您可以像读取UTF-8一样读取字节;如果成功,则定义为有效的UTF-8。
TA贡献2037条经验 获得超6个赞
这是一个古老的问题,有许多好的答案,但有一件事应该补充。
所有的答案都很笼统。我想补充的是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字符由扩展的ASCII编码(包括UTF-8)中相同的两个字节表示,UTF-8通常用于当前类Unix系统上的脚本和其他文本文件。但是,utf-8文件可能以可选字节顺序标记(Bom)开头;如果“exec”函数专门检测字节0x23和0x21,则BOM(0xEF 0xBB 0xBF)的存在将阻止脚本解释器的执行。一些权威机构建议不要在POSIX(类Unix)脚本中使用字节顺序标记,[14]正是出于这个原因以及更广泛的互操作性和哲学考虑。此外,在UTF-8中,字节顺序标记是不必要的,因为编码不存在Endianness问题;它只用于将编码标识为UTF-8。[强调后加]
BOM在JSON中是非法的
实现不能在JSON文本的开头添加字节顺序标记。
BOM在JSON中是多余的
不仅是非法在JSON中,它也是不需要确定字符编码,因为有更可靠的方法可以明确地确定任何JSON流中使用的字符编码和endianness
BOM破坏JSON解析器
不仅是非法在JSON和不需要,实际上破坏所有软件中显示的方法来确定编码。
确定JSON的编码和endianness,检查NUL字节的前4个字节:
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不会以三个空开始,因此不会被识别。
- UTF-32LE第一个字节后面没有3个空号,因此不会被识别。
- 在前4个字节中,utf-16be只有一个NUL,因此不会被识别。
- 在前4个字节中,utf-16 le只有1个nul,因此不会被识别。
根据实施情况,所有这些可能被错误地解释为UTF-8,然后被误解或拒绝为无效的UTF-8,或者根本不被承认。
此外,如果像我建议的那样对有效的JSON进行实现测试,它甚至会拒绝输入,因为它不会像RFC那样以ASCII字符<128开头,因为输入确实编码为UTF-8。
其他数据格式
JSON中的BOM是不需要的,是非法的,并且破坏了根据RFC正确工作的软件。如果当时不使用JSON应该是个不需要考虑的问题,然而,总是有人坚持使用Boms、注释、不同的引用规则或不同的数据类型来破坏JSON。当然,如果需要的话,任何人都可以自由地使用Boms之类的东西-只是不要叫它JSON。
对于JSON以外的其他数据格式,请查看它的真实外观。如果唯一的编码是UTF-*,并且第一个字符必须是小于128的ASCII字符,那么您已经有了确定数据编码和编码的所有信息。即使将Boms添加为可选功能,也只会使其更加复杂和容易出错。
BOM的其他用途
至于JSON或脚本之外的使用,我认为这里已经有了非常好的答案。我想添加更多关于脚本和序列化的详细信息,因为这是BOM字符导致实际问题的一个例子。
添加回答
举报