UTF-8的BOM之争

BOM的介绍

在github上写md文件的时候,发现生成自己blog时,报出一个错误是让使用UTF-8编码,然后在Notepad++上把文件转成UTF-8时,发现菜单中有"UTF-8无BOM编码格式"。

上网查了一下BOM的定义:byte order mark 这个是为UTF-16和UTF-32准备的,用于标记字节序(byte order)。

「UTF-8」和「带 BOM 的 UTF-8」的区别就是有没有 BOM。即文件开头有没有 U+FEFF。

BOM的爱恨情仇

知乎上有个比较好的文章,讲了BOM问题,下面直接引用了原文:

作者:陈甫鸼 链接:https://www.zhihu.com/question/20167122/answer/14199022 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

首先,BOM是啥。这个就不解释了,Wikipedia上很详细。http://en.wikipedia.org/wiki/Byte_order_mark。在网页上使用BOM是个错误。BOM设计出来不是用来支持HTML和XML的。要识别文本编码,HTML有charset属性,XML有encoding属性,没必要拉BOM撑场面。虽然理论上BOM可以用来识别UTF-16编码的HTML页面,但实际工程上很少有人这么干。毕竟UTF-16这种编码连ASCII都双字节,实在不适用于做网页。其实说BOM是个坏习惯也不尽然。BOM也是Unicode标准的一部分,有它特定的适用范围。通常BOM是用来标示Unicode纯文本字节流的,用来提供一种方便的方法让文本处理程序识别读入的.txt文件是哪个Unicode编码(UTF-8,UTF-16BE,UTF-16LE)。Windows相对对BOM处理比较好,是因为Windows把Unicode识别代码集成进了API里,主要是CreateFile()。打开文本文件时它会自动识别并剔除BOM。Windows用这个有历史原因,因为它最初脱胎于多代码页的环境。而引入Unicode时Windows的设计者又希望能在用户不注意的情况下同时兼容Unicode和非Unicode(Multiple byte)文本文件,就只能借助这种小trick了。相比之下,Linux这样的系统在多locale的环境中浸染的时间比较短,再加上社区本身也有足够的动力轻装前进(吐槽:微软对兼容性的要求确实是到了非常偏执的地步,任何一点破坏兼容性的做法都不允许,以至于很多时候是自己绑住自己的双手),所以干脆一步到位进入UTF-8。当然中间其实有一段过渡期,比如从最初全UTF-8的GTK+2.0发布到基本上所有GTK开发者都弃用多locale的GTK+1.2,我印象中至少经历了三到四年。BOM不受欢迎主要是在UNIX环境下,因为很多UNIX程序不鸟BOM。主要问题出在UNIX那个所有脚本语言通行的首行#!标示,这东西依赖于shell解析,而很多shell出于兼容的考虑不检测BOM,所以加进BOM时shell会把它解释为某个普通字符输入导致破坏#!标示,这就麻烦了。其实很多现代脚本语言,比如Python,其解释器本身都是能处理BOM的,但是shell卡在这里,没办法,只能躺着也中枪。说起来这也不能怪shell,因为BOM本身违反了一个UNIX设计的常见原则,就是文档中存在的数据必须可见。BOM不能作为可见字符被文本编辑器编辑,就这一条很多UNIX开发者就不满意。顺便说一句,即使脚本语言能处理BOM,随处使用BOM也不是推荐的办法。各个脚本语言对Unicode的处理都有自己的一套,Python的 # -- coding: utf-8 --,Perl的use utf8,都比BOM简单而且可靠。另一个好消息是,即使是必须在Windows和UNIX之间切换的朋友也不会悲催。幸亏在UNIX环境下我们还有VIM这种神器,即使遇到BOM挡道,我们也可以通过 set nobomb; set fileencoding=utf8; w 三条命令解决问题。最后回头想想,似乎也真就只有Windows坚持用BOM了。P.S.:本问题是自己的第150个回答。突然发现自己回答得很少很少⋯⋯P.S. 2:突然想起需要解释一下为什么说VIM去除bomb的操作需要在UNIX下完成。因为VIM在Windows环境下有一个奇怪的bug,总是把UTF-16文件识别成二进制文件,而UNIX(Linux或者Mac都可以)下VIM则无问题。这个问题从VIM 6.8一直跟着我到VIM 7.3。目前尚不清楚这是VIM的bug还是我自己那个.vimrc文件的bug。如有高手解答不胜感激。

@引用结束

总结

以下是一些经典语录:

  • HTML有charset属性,XML有encoding属性,没必要拉BOM撑场面
  • UTF-16这种编码连ASCII都双字节,实在不适用于做网页
  • 通常BOM是用来标示Unicode纯文本字节流的,让文本处理程序识别txt文件是哪个Unicode编码(UTF-8,UTF-16BE,UTF-16LE)
  • Windows相对对BOM处理比较好, 打开文本文件时它会自动识别并剔除BOM.
  • Windows的设计者希望能在用户不注意的情况下同时兼容Unicode和非Unicode(Multiple byte)文本文件.
  • Linux一步到位进入UTF-8, 过渡期至少经历了三到四年.
  • BOM不受欢迎主要是在UNIX环境下,因为很多UNIX程序不鸟BOM。因为BOM本身违反了一个UNIX设计的常见原则,就是文档中存在的数据必须可见。
  • UNIX环境下我们还有VIM这种神器,即使遇到BOM挡道,我们也可以通过 set nobomb; set fileencoding=utf8; w 三条命令解决问题。
  • 似乎也真就只有Windows坚持用BOM了。
  • UTF-8不需要BOM, 所以不含BOM的UTF-8才是标准形式.
  • 微软在 UTF-8 中使用 BOM 是因为这样可以把 UTF-8 和 ASCII 等编码明确区分开
  • UTF-8 的网页代码不应使用 BOM,否则常常会出错
  • 写C++代码建议程序要在windows 和 mac 还有linux 上运行的话,源代码最好保存成utf-8 带bom的格式,这样比较通用一些。而用utf-16 无论大端还是小端,g++ 都不认的。或者用utf-8 不带bom格式,然后代码不要出现非ascii 127以后的字符。
  • 带用bom的utf-8也是符合国际标准的
  • 微软在坚持使用bom上没有错,因为这是在为用户考虑的。也许给我们这些写程序的带来了不便,但是,计算机最广泛的用户不是程序员。
  • 带头的鹅和去头的鹅,有些编辑器比较傻会把去头的鹅认成鸭子
  • 以UTF-8格式编码, 从notepad++ --> Mongodb里面复制东西的时候,莫名其妙多了不少的字节数。如果不安装notepad++,使用默认的记事本,那就更是个坑,默认有bom,你还无法选择。
  • 就是因为这个bom,CSV导入mongodb时,第一个字段总是不正常,直接导致用第一个字段作为条件find时,出不了结果!
  • utf8对ascii的兼容确实是它的好,但是这个优点在某些时候恰恰成了隐藏问题的缺点。因此bom大法好,加bom保平安.
  • 为什么windows的记事本要强行给utf8加bom的原因——为了兼容旧系统的编码问题,unix阵营放弃带bom的utf8——为了让它们的上古程序能继续运行下去,这个各自有自己利益诉求的差异决定其实并不对错

参考:

转载于:https://my.oschina.net/u/733473/blog/870542

<think>嗯,用户问的是UTF-8UTF-8 BOM的区别。我需要先回忆一下这两种编码方式的基本概念。首先,UTF-8应该是一种通用的字符编码,支持各种语言,而且它是可变长度的,对吧?而BOM,全称是字节顺序标记,通常用来标识文本的字节序,不过我记得在UTF-8中,字节序其实并不影响,因为UTF-8的字节顺序是固定的。 那UTF-8 BOM到底是怎么回事呢?好像有些系统或程序在保存UTF-8文件时会在文件开头加上BOM,也就是三个字节的EF BB BF。虽然BOMUTF-16或UTF-32中用于确定字节顺序,但在UTF-8里可能更多是作为标识文件编码的标志。但这样做可能会引起问题,比如有些软件无法正确识别BOM,导致开头出现乱码或者解析错误。 接下来要整理它们的区别。首先是BOM的存在与否,UTF-8不带BOM,而UTF-8 BOM则在文件开头有三个字节的标记。然后是兼容性问题,有些旧系统或工具可能不支持BOM,比如PHP在处理文件时如果开头有BOM可能会报错。另外,跨平台处理时,比如Linux和Windows之间的文件交换,BOM可能导致问题。还有应用场景,比如Web开发中通常不建议使用BOM,而某些Windows程序可能需要BOM来正确识别编码。 需要注意的点是,虽然BOM可以帮助识别编码,但现代很多环境和工具已经不需要它了。反而可能因为BOM的存在引发问题,比如脚本文件执行时报错,或者JSON解析失败。要提醒用户根据具体使用场景选择是否添加BOM,比如在Windows的文本文件中有时需要,而在Web开发中应避免。 可能需要举例说明,比如用记事本保存UTF-8时会自动添加BOM,而其他编辑器如Notepad++可以选择是否添加。还要注意不同编程语言对BOM的处理方式,比如Python在读取带有BOM的文件时需要指定编码方式,否则可能出错。 总结的时候要分点明确,用对比的方式列出区别,再给出使用建议,这样用户更容易理解。另外,要使用用户能理解的语言,避免技术术语过多,必要时进行解释。检查是否有遗漏点,比如文件大小的影响,虽然三个字节影响不大,但在某些情况下可能需要注意。最后确保回答结构清晰,步骤合理,符合用户的需求。</think>UTF-8UTF-8 BOM 的区别主要体现在文件编码的标记方式及兼容性上,以下是具体对比: --- ### **1. BOM 标记的存在** - **UTF-8(无 BOM)** 标准 UTF-8 编码不包含任何字节顺序标记(Byte Order Mark, BOM)。文件直接以字符的 UTF-8 字节流开头。 *例如*:`你好` 的 UTF-8 编码是 `E4 BD A0 E5 A5 BD`(无开头标记)。 - **UTF-8 BOM** 在文件开头添加 3 字节的 BOM 标记 `EF BB BF`,用于标识文件为 UTF-8 编码。 *例如*:`你好` 的 UTF-8 BOM 编码是 `EF BB BF E4 BD A0 E5 A5 BD`。 --- ### **2. 兼容性问题** - **UTF-8(无 BOM)** ✅ 广泛兼容,是 Web 开发、Linux/Unix 系统的默认选择。 ✅ 无额外标记,避免解析冲突(如 PHP 脚本开头的 BOM 可能导致 HTTP 头错误)。 - **UTF-8 BOM** ⚠️ 部分旧系统或工具无法识别 BOM,可能导致以下问题: - 文件开头显示乱码(如 ``)。 - 脚本执行错误(如 Python 报错 `SyntaxError: encoding problem`)。 - JSON 解析失败(BOM 违反 RFC 标准)。 --- ### **3. 典型应用场景** | **场景** | **推荐编码** | **原因** | |------------------------|------------------|-----------------------------------| | Web 开发(HTML/CSS/JS)| UTF-8(无 BOM) | 避免浏览器解析冲突 | | Windows 文本文件 | UTF-8 BOM | 帮助记事本等工具正确识别编码 | | 跨平台开发(如 Python)| UTF-8(无 BOM) | 避免解释器报错 | --- ### **4. 如何选择?** - **使用 UTF-8 BOM 的情况** - 需兼容旧版 Windows 软件(如记事本)。 - 文件需要明确标识编码(但现代编辑器已支持自动检测)。 - **使用 UTF-8(无 BOM)的情况** - 开发 Web 应用或 API。 - 编写脚本或配置文件。 - 确保跨平台一致性(Linux/macOS/Windows)。 --- ### **示例对比** ```plaintext # UTF-8(无 BOM) 48 65 6C 6C 6F → "Hello" # UTF-8 BOM EF BB BF 48 65 6C 6C 6F → "Hello"(带 BOM 标记) ``` --- ### **注意事项** - 修改文件编码时,需通过编辑器明确选择是否添加 BOM(如 Notepad++ 的 `Encoding > UTF-8` vs `UTF-8-BOM`)。 - 编程中建议通过代码声明编码(如 Python 的 `# -*- coding: utf-8 -*-`),而非依赖 BOM
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值