字符编码详解
发布于 4 个月前 作者 albert 434 次浏览 来自 分享

  经常有人问,为啥出来乱码呢?要么是前端浏览器显示乱码,要么是后台服务器接收是乱码。前两天又碰到一哥们儿来问我这问题!那么,今天就来聊聊字符编码。

一、字符编码要解决什么问题?

  就一句话,解决二进制与字符相互转换的问题!够直白吧!

二、字符编码是如何工作的?

  以ASCII编码为例,规定以一个字节来表示一个字符,一个字节8位(11111111),一共可以表示256个字符,目前只用到0-127号。

ASCII码表

  有了这个规则,那么字符在网络间传输时就可以按照这个规则进行编码解码。

编码解码过程.png

  上图是以一个大写的字符A为例,基于ASCII编码字符集的编码解码过程。

三、各种字符编码间是何种关系?

  谈到字符编码,就会有人问UTF-8GB2312到底啥关系,跟ASCII编码又是啥关系?
  还是一句话,他们相互间无直接关系!
  解释一下,可以简单粗暴的理解为每一种字符编码对应于一种语言字符与二进制间的转换Map关系,最终形成一个字符集。当初设计的时候,只考虑到英文字符,用ASCII绰绰有余。但是后来碰到日文字符、中文字符、阿拉伯语字符等当然就不好使了,而且对于汉字来讲,有上万个字符,一个字节8位显然无法完全表示这么多个汉字字符。这个时候当然需要设计新的字符编码规则来解决不同语言编码的问题。紧接着,世界上的语言那么多种类,如果大家都各自为自己的设计一套,那岂不是很难管理,所以就整出个Unicode来统一标准。
  这里的无直接是指一些编码规则保留了前面127位与最早的ASCII编码相兼容。这也是为什么大部分时候只有中文出现乱码,而英文字符能正常使用的原因。

这里有两篇文章帮助理解:

  1. 字符编码笔记:ASCII,Unicode和UTF-8
  2. ASCII、Unicode、GBK和UTF-8字符编码的区别联系

四、浏览器跟服务器是如何勾搭上的?

  当然,要想勾搭上,当然得先有暗号!这样才能暗送秋波。不然两边各自讲相互听不懂的语言当然就无法沟通。

名称 说明 样例
Accept-Charset 客户端告诉服务器接收哪种字符编码 Accept-Charset:utf-8,is0-8859-1;1=0.8,q表示优先级,1最高
charset 告诉接收者传输内容使用何种字符编码,这里的接收者既可以是服务器端也可以是客户端 Content-Type: text/html;chart=utf-8

  上面是通过HTTP头信息设置编码规则,还可以在页面上设置编码规则
HTML中:

<HEAD>
  <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-2022-jp">
  <META LANG="jp">
  <TITLE>A Japanese Document</TITLE>
</HEAD>

JSP中:

<%@ page language="java" import="java.util.*" contentType="text/html;charset=utf-8"%>  

JQuery ajax自动设置Content-Type:
  在http://v3.bootcss.com/的console里运行$.ajax({url:"/ajaxDemo",type:"post",data:{name:"YiYing"},success:function(){}}),发起的ajax请求如下图所示:

请求头信息.jpg

jquery 源码:
jquery源码.jpg

五、造成乱码的原因

  查了一下RFC文档,Content-Type的默认值为Content-Type: text/plain; charset=us-ascii。如果客户端的字符A以ASCII编码,最终在网络中传输的是二进制的65。如果服务器以另外一种编码规则解码(这个时候恰好未兼容ASCII),那么通过65解码出来的字符就不是字符A,而是其它字符了,从而造成传说中的乱码。   或者一端用可变长度的UTF-8编码,另一端用ASCII解码(只能表示128个字符,固定一个字节),UTF-8这边如果一个字符占3个字节,如果用ASCII来解码,一个字符被当成3个字符来解码,当然结果就不对。

六、总结

  看到这里,以后碰到乱码问题解决起来就so easy了吧!只需要检查编码与解码规则在哪个环节未对应上即可。

My Blog:Share

2 回复

保持一致就行了,不过在node的世界里,基本都是utf8了。编码后体积不一定小,但是通用可爱~

@DevinXian 要想小可以启用gzip

回到顶部