Appearance
前言
本文记录自己理解 ascii、unicode、utf-8 的含义和区别
ascii 编码
ascii 编码使用一个字节代表一个字符,比如 A,二进制就是 0100 0001,十进制就是 65。目前来说 ascii 只有 128 个字符,所以第一位都统一为 0
unicode 编码
ascii 编码只有 128 种状态,表示英语字符能够,但是表示其他国家语言字符时就不够用, 所以 unicode 编码就是在 ascii 上面扩展到多个字节。所以 unicode 编码将世界上所有符号包括在内。
unicode 只是定义的符号集,但是有些字符需要多字节存储。这个时候有个问题,如何区分多个独立字节表示的多个符号还是表示的一个符号。 有个解决方式都统一成 4 字节或者更高,这个也有个问题是,英语字符需要一个字节,补位会导致存储空间明显变大。
所有的字符均可通过\u0000到\uFFFF来表示,在html中技用&#+10进制来表示 比如'1'表示1或者 \u0031
utf-8
为了解决这个问题,出现 UTF-8、UTF-16、UTF-32 这些解决方案。大部分 unicode 字符都是 2 字节
UTF-8 是一种可变长得编码方式, 可以使用 1-4 个字节来表示一个符号。编码规则只有两条
- 如果是单字节,第一位是 0,剩下用 unicode 编码补齐
- 如果字节是 n(n>1), 前 n 位 1,n+1 位 0, 剩下的每个字节的前两位一律 10, 没有提及的位数使用 unicode 编码补全,
浏览器中有encodeurl和encodeurlComponent两种编码方法,前面那个对大部分保留字都不转义,后面的是严格转义
base64
将二进制从左到右按照3个字节为一组,不满一组的补全0,分成4个 * 6位的数据, 每个前面补全两个0 变成4字节。再将四个字节转换成10进制,按照base64编码表,拼接成字符。存在只有一个字节不能凑成3 * 8 的情况,在后面添加一个或者两个字节,添加了字节后会出现一个或者两个 * 6的情况,这种情况使用=输出。下面对0进行base64编码
- '0'.charCodeAt() => 48 => 48.toString(2) => "00110000"
- 补全 3 * 8 => 00110000 | 00000000 | 00000000 => 明确有两个字节补全添加两个 =
- 调整成 4 * 6 001100 | 000000 | 000000 | 000000 => 注意第二个000000不是补全来的
- 再将 4 * 6 前面添加两位0 补全到 4 * 8 001100 | 0000000 .....
- 换成成10进制 parseInt('00001100', 10) => 12 | 0 | 0 | 0
- 根据base64映射表M | A | = | = 最终的结果就是 MA==
base64由于将3 * 8变成了4 * 8,至少扩大了33%的大小(还有尾部额外的==补全),根据映射表来看组成总是大小写+数字+ "+/="这三类 base64中有/ + = 这对url不友好的字符,所有也有一种url_safe的base64,将/+转换成其他的,将== 取消(因为base64总是4个倍数,不满足的解码时补全)
urlencode %编码方式
url中所有字符必须要是asscii字符集中,而且还需要除去保留字,比如?=#等在url有特殊意义的字符,所以需要通过转义的方式来表达。 url中字符就分为保留字符和非保留字符以及在这两个之外的%。 非保留字符: asscii码中字符,不做处理 保留字符: url中定义的保留字符,将保留字符的拆分成两个16进制表示,再添加%。
html中的转义
html因为将一些符号作为了特殊符号,比如<> = " " ''这些,在html中使用需要转义。所以要想在html中显示<>都需要用转义的方式表达,html中转义基本都是&开头;结尾。浏览器未提供api实现,可通过he.js实现普通字符向html编码转换的过程
