这段时间做的web题比较多,遇到了很多编码的题,所以这里总结一下web方向常用到的编码知识
1.URL编码
首先当我们要去学习一个编码的时候需要知道为什么这里需要编码,通常我们编码的原因是:压缩传输,避免敏感信息泄漏,避免引起歧义等。
URL编码顾名思义就是在URL里的编码,为什么要使用URL编码主要是为了避免引起歧义,比如我们在发送GET请求时 /?a=123&b=234 这里我们传递了两个整数给变量a,b,看似没有问题,如果我们要传递的数据里有?或者&就会引起歧义,浏览器就不知道怎么解析了,所以引入了URL编码,将会引起歧义的地方换成URL编码。
URL编码也叫百分号编码,因为URL编码的形式都是%加上字符的16进制的ASCII码值,比如a的ASCII为97转换成16进制为0x61,所以a的URL编码为%61
但是我们有时在URL里不光会提交英文或者数字,如果URL中出现除ASCII之外的字符怎么办呢,比如中文,这时根据RFC文档推荐我们使用UTF-8对这些字符进行编码,比如“中文”这两个汉字对应的UTF-8编码为0xE4 0xB8 0xAD 0xE6 0x96 0x87,URL编码为%E4%B8%AD %E6%96%87
2.Unicode编码
正如我们前面所看到的仅仅的ASCII编码是根本不够我们使用的,况且世界上有那么多的文字和符号,早期各国各大洲都在研发自己语言系统的字符集,这就造成了一个问题,如果要交流的双方使用的编码和解码的方式不一样那么就会造成乱码,为了解决这一严重影响社会进步的问题,出现了Unicode,正如它的名字一样,它包含了世界上的所有文字字符,给每一个字符都有一个对应的独一无二的编码。
需要注意的是,Unicode 只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。比如,汉字严的 Unicode 是十六进制数4E25,转换成二进制数足足有15位(100111000100101),也就是说,这个符号的表示至少需要2个字节。表示其他更大的符号,可能需要3个字节或者4个字节,甚至更多。
这里就有两个严重的问题,第一个问题是,如何才能区别 Unicode 和 ASCII ?计算机怎么知道三个字节表示一个符号,而不是分别表示三个符号呢?第二个问题是,我们已经知道,英文字母只用一个字节表示就够了,如果 Unicode 统一规定,每个符号用三个或四个字节表示,那么每个英文字母前都必然有二到三个字节是0,这对于存储来说是极大的浪费,文本文件的大小会因此大出二三倍,这是无法接受的。
它们造成的结果是:
1)出现了 Unicode 的多种存储方式,也就是说有许多种不同的二进制格式,可以用来表示 Unicode。
2)Unicode 在很长一段时间内无法推广,直到互联网的出现。
UTF-8
unicode只规定了每一个字符的码点,而怎么存储这个字节就是编码方式了。随着互联网的发展,迫切需要一种可以广泛应用的编码方式,为了有效的解决上面的两个问题便出现了UTF-8,UTF-8只是unicode的一种实现形式而已并不是集合的包含关系。
UTF-8最重要的一个特点就是变长度,随着表示字符的不同字节数会从1到4字节不等。
UTF-8 的编码规则很简单,只有二条:
1)对于单字节的符号,字节的第一位设为0,后面7位为这个符号的 Unicode 码。因此对于英语字母,UTF-8 编码和 ASCII 码是相同的。
2)对于n字节的符号(n > 1),第一个字节的前n位都设为1,第n + 1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的 Unicode 码。
下表总结了编码规则,字母x表示可用编码的位。
JS中的编码方式
JavaScript语言采用Unicode字符集,但是只支持一种编码方法。这种编码既不是UTF-16,也不是UTF-8,更不是UTF-32。上面那些编码方法,JavaScript都不用。 JavaScript用的是UCS-2!
3.HTML字符实体
在 HTML 中,某些字符是预留的。比如:在 HTML 中不能使用小于号(<)和大于号(>),这是因为浏览器会误认为它们是标签。如果希望正确地显示预留字符,我们必须在 HTML 源代码中使用字符实体(character entities)。
字符实体类似这样: