5

Web编码总结

 3 years ago
source link: https://yanhaijing.com/web/2014/12/20/web-charset/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Web编码总结 原创 编辑

20 December 2014
号外号外:我的新书《React状态管理与同构实战》出版啦!!!快点我查看

今天遇到了一个奇怪的问题,两次ajax发送的同一个变量值,后端接收到的编码不一样……,一时间,我竟然发现自己对于编码的问题不能说的很清楚。

lisp主张代码即数据,其实我们写的代码也是数据(信息),数据的存储和传播都要就要涉及到编码的问题。就像我们向对方传递信息之前,先要问对方:can you spreak in english。

小贴士:嗨,你知道吗!windows的换行符是 \r\l,linux的是 \l,mac的是 \r,这是有意还是故意的呢……

本文会试图说清web开发过程中,如下方面的编码问题:

  • HTML编码
  • CSS编码
  • JavaScript编码
  • ajax编码

如果想把编码问题说清楚,那恐怕你看到这里就会把页面关掉了,所以这里仅简要介绍下国内web开发中常用的一些编码。如果你了解或不感兴趣,可以直接跳过本部分。

  • ASCII/EASCII(ISO/IEC 646)
  • GB2312/GBK/GB18030
  • Unicode/UTF8/UTF16

进入数字时代,整个世界都要数字化,最先数字化的就是文字,老外的自我中心论,以为世上仅有abcd…… 26个字母,便发明了ASCII(美国标准信息交换码)。

ASCII 使用一个字节的低7位的不同组合来表示字母数字和一些其他字符,2^7 = 1287位二进制共可以代表128个字母。

后来为了表示更多的字符便将ASCII扩展为8位,称为EASCII,并等同于国际标准ISO/IEC 646

而我们为了让汉语也能数字化,变发明了gb2312,gb2312使用两个字节16位表示汉字,为了兼容ASCII将每个字节的高8位置为1,共有14位可用,2^14 = 16384,但GB 2312标准共收录6763个汉字,后来发现不太够用,又扩展了gbk,gb18030。

终于老外发明了 Unicode,一切都解决了,Unicode有两个字节的16位的编码空间,Unicode是一个归法,比较常用的有UTF8和UTF16两种编码方式。

UTF8在web领域比较常用,是一种变长的编码方式,UTF16是一种定长方式。

最后来看一下,‘回’字的不同编码,要记住哦,后面会多次用到。

162.png

文件编码也可以说是存储的编码。

我们写的代码,最终会以二进制的方式,持久化到计算机的存储设备中。

不同编码的文件,会以不同的规则存储到磁盘中,不同的编码要有自己独特的规则,这样才能在读取的时候不发生冲突,也就是要能识别出来自己,计算机在打开文件的时候都是靠猜测来解码的。

如果存储的编码(算法)和打开的编码(算法)不一致,就会出现乱码的情况。

文件在网络上传入要声明自己的编码,我们一定要清楚源文件的编码,然后才能进行后序工作。

对于前端而言会涉及html,css和js源文件的编码,而国内常用的编码如下:

  • ascii
  • utf-8

推荐大家用utf-8,不容易出问题,但由于历史原因,国内有很多网站的编码都是gbk,下面是BAT的网站情况:

  • qq.com gb2312
  • taobao.com gbk
  • baidu utf-8

百度历史比较悠久的产品线的编码也是gbk,比如百度知道。

网页中HTML的编码由哪些部分决定呢?真正运行在服务器上的HTML编码由下面几部分决定

  • HTTP头
  • user-agent

上面给出的三个因素的权重是由高到低,也就是说HTTP头会覆盖meta的信息。

如果你还不知道什么是HTTP头那么请自行百度,HTTP头中的编码信息如下图中红色方块圈起来的部分,代表当前页面的编码是utf8。用户代理收到这个信息后,就会用utf8编码来将收到的字节流解码。

150.png

有些服务器会设置文件的默认编码信息,有些则不会,后端语言都可以自行设置页面的html编码,在php中设置http编码代码如下:

header("Content-Type:text/html; charset=utf-8");

如果没有设置http头信息,或者在文件系统直接打开页面,html的meta标签就派上了用场,meta中可以设置http头信息,下面的代码和上面php的功能相同:

<meta content="text/html; charset=utf-8" http-equiv="Content-Type">

在html5中将上面的代码简化为如下形式:

<meta charset="utf-8">

如果既没有设置http头,也没有meta标签,那么用户代码会使用系统的默认设置,windows下的中文环境的默认编码一般是 gb2312,所以用户代理就会用gb2312来解码页面,如果页面的编码也刚好是gb2312那么万事ok,否则就会出现乱码。

用户代理一般可以设置默认的编码是什么。比如chrome打开设置下的内容网络,会看到如下的设置界面。

151.png

注:如果最终显示的编码和页面本身的编码不同就会出现乱码。

说完了HTML的编码再来说说CSS的编码,如果HTML文件和CSS文件的编码不一致,那么就需要单独声明才可以。

在html4中link有一个属性——charset可以用来指定引入css文件的编码,但这个属性在html5中已经废弃了,虽然废弃了但在浏览器中还是可以使用的,下面的代码显示指定css文件的编码为gbk。

<link rel="stylesheet" href="gbk-1.css" charset="gbk">

然而html5废弃了这个属性那么该怎么办呢,其实废弃这个属性,是因为把这个功能代理给了css文件,css中有一个@charset指定,可以指定页面的编码,将下面的代码放在css文件的顶部,会显示声明页面的编码为utf8。

@charset utf-8

那么问题来了,如果即设置了charset属性,又设置了@charset指定,结果是@charset指定会覆盖link的charset属性,charset属性已经废弃了,建议用css的@charset指令。

注:如果我们显示指定的编码和css文件的编码不一致也会导致乱码问题。

JavaScript

说清了CSS的编码,我们再来说JavaScript的编码问题,首先还是如果HTML文件的编码和JavaScript文件的编码不一致的话就会产生乱码,这时就需要我们显示声明一下js文件的编码才可以。

html中的script标签有一个charset属性,用来指定引入外部jss文件的编码(字符集)。下面的代码显示声明引入的js的编码是utf8。

<script src="***.js" charset="utf-8"></script>

注:如果我们显示指定的编码和js文件的编码不一致也会导致乱码问题。

其实在JavaScript中仅支持utf16编码,其实也不是utf16,而是utf16的子集——ucs-2,这导致在js中无法表示BMP之外的文字(更多信息请看这里)。

无论js源文件的编码是什么,下面的源代码的输出结果是一样的——前提是解码js的过程正确。

'回'.charCodeAt(0)#输出 22238

22238的十六进制表示是56 DE,而这正是‘回’字的utf16编码。

说ajax之前,先来说说表单提交吧,下面分别是utf8页面和gbk页面的表单提交请求,其中参数name是’回’字。可以看出表单请求的编码是由页面决定的。

http://localhost/github/webtest/charset/form.php?name=%E5%9B%9E
http://localhost/github/webtest/charset/form.php?name=%BB%D8

ajax发送的代码也是由页面决定的,但我们在发送参数前都会encodeURIComponent一下,encodeURIComponent不管页面编码是什么,都会返回utf8编码。

让我们构造一个例子,页面A的编码为gbk,有如下的代码:

xhr.open("GET","form.php?name=" + encodeURIComponent('回') + 'namegbk=' + '回',true);

我们看到发送的ajax请求如下所示:

http://localhost/github/webtest/charset/form.php?name=%E5%9B%9Enamegbk=%BB%D8

这个例子巧妙的验证了上面的结论。

再来说说json,json只支持utf8编码,所以不要返回gbk编码的json。

161.png

在信息交换的任何一个环节,如果编码信息和解码信息不一致都会产生乱码问题。

本文中的所有例子都可以从webtest下载。

关于编码还有很多东西可以需要学习,我强烈建议你可以阅读下参考资料里面的一些文章,同时我还建议您阅读”code“这本书。

163.png

原文网址:http://yanhaijing.com/web/2014/12/20/web-charset/

微信公众号:颜海镜关注微信公众号 颜海镜微信支付二维码赞赏支持 微信扫一扫

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK