php UTF-8、Unicode和BOM问题


Posted in PHP onMay 18, 2010

一、介绍

UTF-8 是一种在web应用中经常使用的一种 Unicode 字符的编码方式,使用 UTF-8 的好处在于它是一种变长的编码方式,对于 ANSII 码编码长度为1个字节,这样的话在传输大量 ASCII 字符集的网页时,可以大量节约网络带宽。
UTF-8签名(UTF-8 signature)也叫做BOM(Byte Order Mark),是UTF编码方案里用于标识编码的标准标记。BOM,是UTF编码方案里用于标识编码的标准标记,在UTF-16里本来是FF FE,变成UTF-8就成了EF BB BF。这个标记是可选的,因为UTF8字节没有顺序,所以它可以被用来检测一个字节流是否是UTF-8编码的。微软做这种检测,但有些软件不做这种检测,而把它当作正常字符处理。微软在自己的UTF-8格式的文本文件之前加上了EF BB BF三个字节, windows上面的notepad等程序就是根据这三个字节来确定一个文本文件是ASCII的还是UTF-8的, 然而这个只是微软暗自作的标记, 其它平台上并没有对UTF-8文本文件做个这样的标记。也就是说一个UTF-8文件可能有BOM,也可能没有BOM。
只有一个BOM,是不会有问题的。如果多个文件设置了签名,在二进制流中就会包含多个UTF-8签名,也就是导致XML转换失败的"root element must be well-formed"原因。

二、查看和转换

既然一个UTF-8文件可能有BOM,也可能没有,那该如何区分呢?
只要用带十六进制编辑方式的软件,例如,用UltraEdit-32打开文件,切换到十六进制编辑模式,察看文件头部是否有EF BB BF。有,则为带BOM方式。
Windows自带的notepad记事本,保存为UTF-8时,默认就带BOM。
转换的方法有很多,常见的UltraEdit-32或NotePad++都可以,以UltraEdit-32为例。打开文件后,选择“另存为”,在“格式”一栏中有如下选择:

php UTF-8、Unicode和BOM问题

另外,DreamWeaver CS3也有类似的选项,在“首选项”中,如果选择 Unicode (UTF-8) 作为默认编码,则可以选择“包括 Unicode 签名 (BOM)”选项,以在文档中包括字节顺序标记 (BOM)。否则,不带BOM:
php UTF-8、Unicode和BOM问题
三、其他知识
从http://blog.csdn.net/thimin/archive/2007/08/03/1724393.aspx 一文了解到:
所谓的unicode保存的文件实际上是utf-16,只不过恰好跟unicode的码相同而已,但在概念上unicode与utf是两回事,unicode是内存编码表示方案,而utf是如何保存和传输unicode的方案。utf-16还分高位在前 (LE)和高位在后(BE)两种。官方的utf编码还有utf-32,也分LE和BE。非unicode官方的utf编码还有utf-7,主要用于邮件传输。utf-8的单字节部分是和iso-8859-1兼容的,这主要是一些旧的系统和库函数不能正确处理utf-16而被迫出来的,而且对英语字符来说,也节省保存的文件空间(以非英语字符浪费空间为代价)。在iso-8859-1的时候,utf8和iso-8859-1都是用一个字节表示的,当表示其它字符的时候,utf-8会使用两个或三个字节。

一段关于BOM的更详细说明,来自这里:
在UCS 编码中有一个叫做"ZERO WIDTH NO-BREAK SPACE"的字符,它的编码是FEFF。而FFFE在UCS中是不存在的字符,所以不应该出现在实际传输中。UCS规范建议我们在传输字节流前,先传输字符"ZERO WIDTH NO-BREAK SPACE"。这样如果接收者收到FEFF,就表明这个字节流是Big-Endian的;如果收到FFFE,就表明这个字节流是Little-Endian的。因此字符"ZERO WIDTH NO-BREAK SPACE"又被称作BOM。
UTF-8不需要BOM来表明字节顺序,但可以用BOM来表明编码方式。字符"ZERO WIDTH NO-BREAK SPACE"的UTF-8编码是EF BB BF。所以如果接收者收到以EF BB BF开头的字节流,就知道这是UTF-8编码了。
Windows就是使用BOM来标记文本文件的编码方式的。

PHP也不支持BOM。
PHP在设计时就没有考虑BOM的问题,也就是说他不会忽略UTF-8编码的文件开头BOM的那三个字符。由于必须在<?或者<?php后面的代码才会作为PHP代码执行,所以这三个字符将会直接输出。如果插件的文件有这个问题,将会导致在后台页面里激活或者不激活插件后显示白屏,如果是模版文件有这个问题,将会导致这三个字符直接输出,造成页面上方有一个小空行。国外的英文插件和模版一般都是用的ASCII码的编码方式,不会有BOM,只有国内的插件和模版会由于作者的不知情造成问题。还有,大家修改模版的时候,由于输出页面使用UTF-8编码,那么修改模版的时候如果有加入中文字符的话,必须把文件转成UTF-8编码才能正常显示,这个时候如果所使用的编辑器自动加上了BOM的话,将会造成在页面上输出这三个字符,显示效果就要看浏览器了,一般是一个空行或是一个乱码。
※ 补充一句:特别是当使用php导入模板的时候,更容易因为这三个字符,导致浏览异常。

PHP 相关文章推荐
杏林同学录(六)
Oct 09 PHP
Breeze 文章管理系统 v1.0.0正式发布
Dec 14 PHP
PHP 多维数组的排序问题 根据二维数组中某个项排序
Nov 09 PHP
PHP批量上传图片的具体实现方法介绍.
Feb 26 PHP
php的mkdir()函数创建文件夹比较安全的权限设置方法
Jul 28 PHP
从零开始学YII2框架(一)通过Composer安装Yii2框架
Aug 20 PHP
PHP使用gmdate实现将一个UNIX 时间格式化成GMT文本的方法
Mar 19 PHP
ThinkPHP自定义函数解决模板标签加减运算的方法
Jul 03 PHP
摘自织梦CMS中的图片处理类
Aug 08 PHP
Yii2隐藏frontend/web和backend/web的方法
Dec 12 PHP
php利用ob_start()清除输出和选择性输出的方法
Jan 18 PHP
Laravel框架自定义验证过程实例分析
Feb 01 PHP
php生成的html meta和link标记在body标签里 顶部有个空行
May 18 #PHP
PHP 工厂模式使用方法
May 18 #PHP
在PHP中使用反射技术的架构插件使用说明
May 18 #PHP
PHP 写文本日志实现代码
May 18 #PHP
php 随机记录mysql rand()造成CPU 100%的解决办法
May 18 #PHP
PHP array_flip() 删除重复数组元素专用函数
May 16 #PHP
mysql下创建字段并设置主键的php代码
May 16 #PHP
You might like
php验证手机号码(支持归属地查询及编码为UTF8)
2013/02/01 PHP
php使用strtotime和date函数判断日期是否有效代码分享
2013/12/25 PHP
php可生成缩略图的文件上传类实例
2014/12/17 PHP
ThinkPHP5分页paginate代码实例解析
2020/11/10 PHP
JS支持带x身份证号码验证函数
2008/08/10 Javascript
给angular加上动画效遇到的问题总结
2016/02/17 Javascript
jQuery的deferred对象使用详解
2016/09/25 Javascript
原生JS版和jquery版实现checkbox的全选/全不选/点选/行内点选(Mr.Think)
2016/10/29 Javascript
微信公众号开发 实现点击返回按钮就返回到聊天界面
2016/12/15 Javascript
静态页面实现 include 引入公用代码的示例
2017/09/25 Javascript
Angular中管道操作符(|)的使用方法
2017/12/15 Javascript
layui点击按钮添加可编辑的一行方法
2018/08/15 Javascript
Layui给数据表格动态添加一行并跳转到添加行所在页的方法
2018/08/20 Javascript
小程序api实现promise封装过程解析
2019/11/21 Javascript
python str与repr的区别
2013/03/23 Python
利用python爬取斗鱼app中照片方法实例
2017/12/03 Python
OpenCV-Python实现轮廓检测实例分析
2018/01/05 Python
Django框架使用mysql视图操作示例
2019/05/15 Python
python中的selenium安装的步骤(浏览器自动化测试框架)
2020/03/17 Python
python实现超级玛丽游戏
2020/03/18 Python
Python写捕鱼达人的游戏实现
2020/03/31 Python
Jupyter Notebook 文件默认目录的查看以及更改步骤
2020/04/14 Python
python 读取yaml文件的两种方法(在unittest中使用)
2020/12/01 Python
解决Firefox下不支持outerHTML问题代码分享
2014/06/04 HTML / CSS
赫里福德的一家乡村零售商店:Philip Morris & Son
2017/06/25 全球购物
课前三分钟演讲稿
2014/04/24 职场文书
优秀教导主任事迹材料
2014/05/09 职场文书
文明家庭先进事迹材料
2014/05/14 职场文书
三分钟自我介绍演讲稿
2014/08/21 职场文书
个人委托书范本
2014/09/13 职场文书
年度考核登记表个人总结
2015/03/06 职场文书
2016大学生社会实践单位评语
2015/12/01 职场文书
银行大堂经理培训心得体会
2016/01/09 职场文书
九年级化学教学反思
2016/02/22 职场文书
JavaScript嵌入百度地图API的最详细方法
2021/04/16 Javascript
Python爬虫之爬取最新更新的小说网站
2021/05/06 Python