编码发展
1. ASCII - 早期阶段
ASCII(American Standard Code for Information Interchange:美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统,主要用于显示现代英语和其他西欧语言。
早只有 127 个字符被编码到计算机里,也就是大小写英文字母、数字和一些符号,这个编码表被称为 ASCII 编码,比如大写字母 A 的编码是 65,小写字母 z 的编码是 122。
2. GB2312、GBK - 各国自主编码阶段
有几万字的中文,如果处理中文显然一个字节是不够的,至少需要两个字节,而且还不能和 ASCII 编码冲突,所以,中国制定了 GB2312、GBK、GB 编码,用来把中文编进去;
Shift_JIS、Euc-kr 全世界有上百种语言,日本把日文编到 Shift_JIS 里,韩国把韩文编到 Euc-kr 里,各国有各国的标准,就会不可避免地出现冲突,结果就是,在多语言混合的文本中,显示出来会有乱码。
GB2312
GB2312 或 GB2312–80,是中华人民共和国国家标准简体中文字符集,1981 年 5 月 1 日实施。GB2312 编码通行于中国大陆;新加坡等地也采用此编码。GB2312 标准共收录6763 个汉字,其中一级汉字 3755 个,二级汉字 3008 个;
GB2312 的出现,基本满足了汉字的计算机处理需要,它所收录的汉字已经覆盖中国大陆 99.75%的使用频率。但对于人名、古汉语等方面出现的罕用字和繁体字,GB2312 不能处理,因此后来 GBK
GBK
GBK 只为“技术规范指导性文件”,不属于国家标准。GBK,全名为《汉字内码扩展规范(GBK)》1.0 版,由中华人民共和国全国信息技术标准化技术委员会 1995 年 12 月 1 日制订,GBK 的 K 为“扩展”的汉语拼音(kuòzhǎn)第一个声母。
GBK 是一种编码方式并向下兼容 GB2312,GBK 共收录21886 个汉字和图形符号,其中汉字(包括部首和构件)21003 个,图形符号 883 个。随后,国家质量技术监督局于 2000 年 3 月 17 日推出了GB18030-2000标准,以取代 GBK。
3. Unicode 万国码 - 全球编码标准过程
Unicode 把所有语言都统一到一套编码里,这样就不会再有乱码问题了。
1993 年,Unicode 1.1 版本推出,收录中国大陆、台湾、日本及韩国通用字符集的汉字,总共有20,902 个。中国大陆订定了等同于 Unicode 1.1 版本的“GB 13000.1-93”
4. UTF-8、UTF-16 - 基于 Unicode,从存储和传输效率考虑
UTF-8(8-bit Unicode Transformation Format)是一种针对 Unicode 的可变长度字符编码,也是一种前缀码。它可以用来表示 Unicode 标准中的任何字符,且其编码中的第一个字节仍与 ASCII 兼容,这使得原来处理 ASCII 字符的软件无须或只须做少部分修改,即可继续使用。
UTF-8 使用一至六个字节为每个字符编码,这些多字节的最高有效比特会设置成 1(尽管如此,2003 年 11 月 UTF-8 被 RFC 3629 重新规范,只能使用原来 Unicode 定义的区域,U+0000 到 U+10FFFF,也就是说最多四个字节),:
- 128 个 US-ASCII 字符只需一个字节编码(Unicode 范围由 U+0000 至 U+007F)。
- 带有附加符号的拉丁文、希腊文、西里尔字母、亚美尼亚语、希伯来文、阿拉伯文、叙利亚文及它拿字母则需要两个字节编码(Unicode 范围由 U+0080 至 U+07FF)。
- 其他基本多文种平面(BMP)中的字符(这包含了大部分常用字,如大部分的汉字)使用三个字节编码(Unicode 范围由 U+0800 至 U+FFFF)。
- 其他极少使用的 Unicode 辅助平面的字符使用四至六字节编码(Unicode 范围由 U+10000 至 U+1FFFFF 使用四字节,Unicode 范围由 U+200000 至 U+3FFFFFF 使用五字节,Unicode 范围由 U+4000000 至 U+7FFFFFFF 使用六字节)。
5. Python 中处理
|
|
其他编码相关内容
1. URL 编码、百分号编码
百分号编码, 也称作 URL 编码, 是特定上下文的统一资源定位符 (URL)的编码机制,实际上也适用于统一资源标志符(URI)的编码;也用于为application/x-www-form-urlencoded
MIME 准备数据, 因为它用于通过 HTTP 的请求操作(request)提交 HTML 表单数据。
编码方式:
当前是采用RFC 3986
标准,建议所有新的 URI 必须对未保留字符不加以百分号编码,对其他非 ASCII 字符, 需要转换为 UTF-8 字节序, 然后每个字节按照上述方式表示,比如汉字等;
- 保留字与未保留字
- 保留字:诸如
!*'();:@&=+$,/?#[]
这类有特殊含义的字符 - 未保留字:诸如
abc-z,ABC-Z,1-9,-_.~
- 保留字:诸如
- 若保留字需要特殊含义,该字符必须百分号编码;
/
为具有特殊含义的保留字符,如果在 URI 路径侧,则需要百分号编码; - 字符
%
号需要特殊编码为%25
- 空格被编码为
%20
,有的则被编码成+号
(有很多小的修改如新行规范化以及把空格符的编码%20
替换为+
)
转码效果
|
|
表单提交中的编码
- 如果发送的是 HTTP GET 请求,
application/x-www-form-urlencoded
数据包含在所请求 URI 的查询成分中. - 如果发送的是 HTTP POST 请求或通过 email, 数据被放置在消息体中,媒体类型的名字被包含在消息的 Content-Type 头内部。
|
|
2. Base64 编码
Base64 是一种基于 64 个可打印字符来表示二进制数据的表示方法
由于2^6=64
,所以每 6 个比特为一个单元,对应某个可打印字符的 3 个字节有 24 个比特,对应于 4 个 Base64 单元,即原来 3 个字节需要由 4 个 Base64 中可打印的字符来表示,故经过 Base64 编码后的的长度,为原数据长度的4/3
,根据 RFC 822 规定,每76
个字符,还需要加上一个回车换行。可以估算编码后数据长度大约为原长的135.1%
。
在 Base64 中的可打印字符包括字母A-Z、a-z、数字0-9
,这样共有 62 个字符,此外两个可打印符号在不同的系统中而不同:
- 通用 MIME 中:
加号+
和斜杠/
- 用于 URL 的改进 Base64 编码:
-
和_
,它不在末尾填充=号
- 用于正则表达式的改进 Base64 变种,它将
+
和/
改成了!
和-
- 等号
=
用来作为后缀用途
编码过程
- 转换的时候,将 3 字节的数据,先后放入一个 24 位的缓冲区中,先来的字节占高位。
- 数据不足 3 字节的话,于缓冲器中剩下的比特用 0 补足。
- 每次取出 6 比特,按照其值选择 ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/中的字符作为编码后的输出,直到全部输入数据转换完成。
- 若原数据长度不是 3 的倍数时且剩下 1 个输入数据,则在编码结果后加 2 个=;若剩下 2 个输入数据,则在编码结果后加 1 个=。
编码用途
Base64 常用于在通常处理文本数据的场合,表示、传输、存储一些二进制数据,Base64 它可用来作为电子邮件的传输编码、Base64 图片编码等:
- 隐私增强邮件
- MIME:(多用途互联网邮件扩展)规范列出 Base64 编码为两个中的一个二进制到文本编码方案(比如邮件内嵌图片)
- UTF-7:它是 MIME 中使用的 Base64 编码的变体。
- 文件名:修改打印符,使用
-
而不是/
,因为文件名不能含/
,可以基于修改后的 Base64 再用于 URL - URL 紧凑:在 HTTP 环境中使用相当冗长的标识信息时,Base64 编码会很有用。
- 在 URL 中使用标准 Base64 需要将
+
,和=
字符编码为特殊的百分比编码的十六进制序列(+
变为%2B
,/
变为%2F
和=
变为%3D
),这使得字符串不必要地更长。 - URL 增强中,标准的 Base64 编码将字符
+
和/
分别由-
和_
替代
- 在 URL 中使用标准 Base64 需要将
- HTML 中:
atob()
和btoa()
,javaScript 方法为网页提供了 Base64 编码和解码功能。 - Base64 用于编码脚本中的二进制文件(如图像),以避免依赖外部文件。
data URI方案
可以使用 Base64 编码来表示文件的内容。例如,背景图像和字体可以在 CSS 样式表文件中指定为data:URI
,而不是在单独的文件中提供。
3. Base58 编码(64 字符-6=58)
Base58 是用于 Bitcoin 中使用的一种独特的编码方式,主要用于产生 Bitcoin 的钱包地址。相比 Base64,Base58 不使用数字0
,字母大写O
,字母大写I
,和字母小写l
,以及+
和/
符号。
设计 Base58 主要的目的是:
- 避免混淆。在某些字体下,数字 0 和字母大写 O,以及字母大写 I 和字母小写 l 会非常相似。
- 不使用"+“和”/“的原因是非字母或数字的字符串作为帐号较难被接受。
- 没有标点符号,通常不会被从中间分行。
- 大部分的软件支持双击选择整个字符串。