HTML5标准学习 - 编码
2011-09-25 19:09
169 查看
from:/article/4951035.html
相信每一个前端工程师都或多或少遇上过“乱码”这位仁兄,无论你的基础有多么扎实,在生产的过程中都免不了偶尔和“乱码”兄弟喝上几杯茶吧。作为一个前端工程师,你是如何指定一个页面的编码的呢?你知道浏览器是怎么识别编码的吗?首先,一个很简单的例子,用遇简的HTML页面来看看各浏览器下有什么不同:
<!DOCTYPE html>
最简HTML,
<head>和
<body>都没有内容,服务器也不给出具体的编码声明,直接从本地打开,各个浏览器下查看页面的编码:
浏览器 | 显示编码 | 备注 |
---|---|---|
IE6 | UTF-8 | |
IE8 | UTF-8 | |
IE9 | GB2312 | 系统默认字符集 |
Firefox3.5 | GBK2312 | 系统默认字符集 |
Firefox4.0 | ISO-8859-1 | 西欧语言,英语默认编码 |
Chrome | GBK | 系统默认字符集 |
Opera | 中文-自动检测 | 应该也是GB2312 |
编码声明
HTML4和HTML5分别采用了一个章节来阐述编码声明的方法,可以点击这里查看HTML4的相关章节或点击这里查看HTML5的相关章节。首先,何为编码?编码即是通过一定的方式,指定浏览器(或称用户代理)以一种特殊的算法来解析字节流,以得到真正正确的内容。在HTML的标准中,编码可以使用别名来表示。编码的别名来自于IANA的定义,只有在该列表中出现的编码才可以被浏览器识别。因此如果把UTF-8写成UTF8,浏览器就有可能完全不予理睬。另外,编码别名是大小写不敏感的。
在HTML4中,提出有3种方法指定页面的编码,根据优先级高低依次是:
HTTP头里的Content-Type字段后跟随字符集。
使用
<meta http-equiv="Content-Type">标签来声明。
对于部分外部资源,如
<script>标签加载的js文件,可以通过标签上的charset属性声明。
这个自然没有什么疑问,需要注意的是,通过
<meta http-equiv="Content-Type">标签来声明页面的话,当浏览器遇上该标签时,如果发现自己使用的编码与标签声明的不符,是会回到头里重新解析页面的。这会导致页面的一部分被重新解析,因此如果试图使用标签的方式声明编码的话,建议将标签尽可能地写在前面。一个最佳实践是写在
<head>标签之后,任何其他标签之前。关于这一点,Google PageSpeed也有相应的介绍。
时代演进
但是随着时间的推移,开发者渐渐发现了一件事。就如同DOCTYPE的最简声明一样,其实浏览器在读取<meta>标签的编码的时候,并不是严格地按照标准进行的。总而言之,由于在HTML的解析阶段,基于在Tokenizer阶段之前就必须确定好页面的编码,因此浏览器不可能像分析DOM树一样,在DOM树构建的时候再分解
<meta>标签的结构,取出其中的
http-equiv和
content属性,再确定编码。
现实中,浏览器做了一件非常简单的事,来读取
<meta>标签定义的编码:
确定这是一个
<meta>标签,这根据HTML解析的状态机,由"<"字符加上"meta"字符串就能确定。
查找该字符串(此处还没有标签的概念,只是个字符串),找到一个子字符串"charset"。
再向后读,忽略掉所有的空格字符,找到第一个有意义的字符c。
如果c不是"="这个字符,则回到第2步继续找。
如果c是"="这个字符,继续向下走。
再跳掉所有的空格字符和单引号、双引号等,向后扫描,直到遇上单引号、双引号、空格字符、结束标签等不应该出现的字符为上,截取其中扫描得出的字符串s。
分析s,得到编码别名。
从上面的算法,不难发现,下面几种写法,其实都能让浏览器正确地识别出编码:
<meta http-equiv="Cotnent-Type" content="text/html; charset=utf-8" />
<meta charset="utf-8" />
<meta charset=utf-8 />
……以及其他很多古怪的写法。
于是,随着历史的推进,终于有一天,各浏览器厂商们坐在了一起,开始讨论这个问题……最终他们惊奇地发现各自的实现非常相似(也许根本就是相互借 鉴),所以他们决定将这种方式变成一个标准……最后,再经过漫长的讨论,HTML5中广为人爱的编码声明方式就诞生了。在HTML5中,称其为“meta charset元素”,其最简形式如下:
<meta charset=utf-8>
当然这是HTML的语法,如果遵从XHTML并觉得XHTML更加亲切地话,写成
<meta charset="utf-8" />也是没问题的。
而前文所述的具体获取编码的算法也被详细地记录在案,可以在这里看到。
到了HTML5时代,标准再次对编码的声明方式做了修正和细化,总得来说有以下的区别:
HTML5允许使用BOM来决定编码,但仅支持UTF-16的BOM(即U+FEFF),且没有说明BOM指定编码的优先级如何。
HTML5添加了
meta charset标签。
HTML5规定如果一个页面没有指定编码,则使用ASCII作为其编码,而HTML4则规定浏览器可以根据所处的环境自行选择。
其他杂项
除了编码的基本声明方式外,标准中还有不少需要注意的细节:如果使用
<meta>标签声明编码的话,该编码只能是ASCII的超集编码。可以简单地认为ASCII超集就是支持ASCII的256个字符的编码。
HTML5非常推荐使用UTF-8编码。
标准中提出不要使用UTF-32、JIS_C6226-1983、JIS_X0212-1990、HZ-GB-2312、JOHAB等字符集,并禁止使用CESU-8、UTF-7、BOCU-1和SCSU字符集。但事实上浏览器却至少能识别UTF-7。
对于想要严格遵守XHTML的开发者,应当使用XML声明来指定编码,即
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>。但是这个在IE6下会影响到DOCTYPE,所以开发者也不得在这一点上给予妥协,乖乖地去用HTML的声明方式。
关于现实中各编码声明方式的优先级,以及一些其他需要注意的细节,这篇文章值得一读。
最佳实践
尽可能使用HTTP头指定编码。尽可能使用UTF-8,或者至少全站所有资源使用统一编码。
如果想使用UTF-16,就给文件加上BOM,以确定是Little Endian还是Big Endian的。
如果使用
<meta>标签指定编码,可以不使用http-equiv的形式,但尽可能让标签出现在前面,至少保证在任何非ASCII字符之前。
链接外部的脚本,如果无法确定编码相同的话,加上charset属性。
相关文章推荐
- HTML5标准学习 - 编码
- HTML5标准学习---编码(转载)
- HTML5标准最终来了,看什么书学习最好??????
- HTML5标准终于来了,看什么书学习最好??????
- HTML5风格指南与编码标准
- 视频编解码学习之四:视频处理及编码标准
- HTML5标准学习 – 简介
- FreeRTOS系列学习笔记一---FreeRTOS编码标准及风格指南
- HTML5标准学习 - 文档结构
- HTML5标准终于来了,看什么书学习最好??????
- 视频编解码学习之四:视频处理及编码标准
- HTML5标准终于来了,看什么书学习最好??????
- HTML5标准终于来了,看什么书学习最好??????
- FreeRTOS学习笔记-1-Coding Standard and Style Guide(编码标准和风格)
- 视频编解码学习之四:视频处理及编码标准
- 视频编解码学习之四:视频处理及编码标准
- 视频编解码学习之四:视频处理及编码标准
- HTML5标准学习 – DOCTYPE
- 谷歌VP9欲颠覆HTML5标准:新视频编码减小6成体积
- 谷歌逆袭html5标准:新编码减6成体积