一文弄懂 URLEncode 及GBK, Unicode

2019 年 9 月 17 日 余晟以为

按:我相信有许多程序员搞不清楚Unicode和UTF-8的关系,这不稀奇,因为我以前也搞不懂。后来为了写《正则指引》(第2版)才彻底搞懂,并且专门新增了一章谈这个话题。如果你和我之前一样不太清楚其中的区别,也没看过《正则指引》,不妨看看我的朋友胡永浩的这篇文章,相信会有收获。

URL encode

URL encode 实际上是对 URI 进行 encode的,而不是对 URL

什么是 URI?

Uniform Resource Identifier (URI,统一资源标志符) ,是用来标识资源的字符串,规定了以下文法:



上图可见,有效的 URI 至少包含 scheme: 以及 path(路径),如经典的触发操作系统发邮件动作的mailto 格式[1]

  mailto:John.Doe@example.com  └─┬──┘ └────┬─────────────┘  scheme     path

其他就是可选的组合路径了,如 scheme://host path ? query # fragment 就会我们常见的 url 格式:

          userinfo       host      port          ┌──┴───┐ ┌──────┴──────┐ ┌┴┐  https://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top  └─┬─┘   └───────────┬──────────────┘└───────┬───────┘ └───────────┬─────────────┘ └┬┘  scheme          authority                  path                 query           fragment

URI包含URLs and URNs

URL:Uniform Resource Locator(统一资源定位符):定义了如何找到一个资源URN: Uniform Resource Name (统一资源名称):定义了这个资源的唯一名字

简单说作用就是:

URL:我们目前常用的网站地址,提供了以什么协议(http,ftp)来访问,地址路径在哪里(bilibili.com, abc.com)等等。URN:我要获取的这个资源有一个唯一名字,我提供过去,统一中心会解析这个 URN,不管这个资源搬迁到哪里,只要存在就会返回给你。而 URL 一旦搬迁了,就不是有效地址了,你需要一个新地址去定位这个资源。但是由于历史原因,URN 几乎没有普及,所以某种程度上给人造成了 URL 跟 URI 好像差不多的样子。

Reserved Characters(保留字符)

URI 规定了要保留以下字符作特殊使用:

!    *    '    (    )    ;    :    @    &    =    +    $    ,    /    ?    #    [    ]来自 RFC 3986 section 2.2 Reserved Characters (January 2005)

如 ? 用来带 url 中的参数,/ 用来分割 url, & 用来拼接 query等,保留字符都有自己的作用。

因此需要传此类字符而不是作特殊字符作用使用时,不能直接放入 url 中,需要编码,也就是 url encode 做的事情。

encode 很简单,把保留字符如 ? 转成 ASCII[2] 的 16 进制表示(? 就是 3F),在前面加一个 % 代表这是转码字符即可,也就是 ? 需要 encode 成 %3F 放在 url 中,所以 url encode 又称作 Percent-encoding

实际应用

url 中,需要传入跳转 BACK_URL 参数 new_login.com?a=12 时,就需要转移 ? 跟 =g .

https://third_party_login.com?BACK_URL=new_login.com?a=12 

就应该转换成

https://third_party_login.com?BACK_URL=new_login.com%3Fa%3D12

这样子后面的 ? 与 = 就不会被处理掉,而能够作为 BACK_URL 这个参数的一部分传给后端。

http 协议中 headers 的 content-type 里常见的的 application/x-www-form-urlencoded,指定请求 body 使用 URL encoded

gbk,Unicode,UTF-8

鉴于珠玉在前,我就整理下Unicode 和 UTF-8 有什么区别?[3]的内容 ok 了:

简单来说:

Unicode 是「字符集」UTF-8 是「编码规则」字符集:为每一个「字符」分配一个唯一的 ID(学名为码位 / 码点 / Code Point)。可以理解为“所有学生的学号的集合”。编码规则:将「码位」转换为字节序列的规则(编码 / 解码 可以理解为 加密 / 解密 的过程)。可以理解为“每个学号的写法,有时用“347”,有时用“三四七“,有时用”叁肆柒“。

详细过程:

在没有Unicode的年代,为了表示中文字符,中国人民通过对 ASCII 编码扩充改造,产生了 GB2312 编码,可以表示 6000 多个常用汉字。GB2312 编码是变长编码,向下兼容ASCII 编码,也就是说,每个英文字母以1个字节表示,每个汉字以2个字节表示,总共包含了6763个汉字。汉字实在是太多了,包括繁体和各种字符,于是产生了 GBK 编码,它是 GB2312 的超集,向下兼容GBK 编码,同时扩充了很多内容(比如“朱镕基总理”的“镕”就是不在GB2312而在GBK 编码中的),总汉字数达到了20902个。中国是个多民族国家,各个民族几乎都有自己独立的语言系统,为了表示那些字符,继续把 GBK 编码扩充为 GB18030 编码,可容纳汉字数达到了七万多个。每个国家都像中国一样,把自己的语言编码,于是出现了各种各样的编码,如果你不安装相应的编码,就无法解释相应编码想表达的内容。这还不是最要紧的,最要紧的是,如果一段文字同时包含多国文字,比如既有中文又有日本还有韩文,从技术上讲,是不可能正常显示的。终于,有个叫 ISO(国际标谁化组织) 的组织看不下去了。他们创造了一种编码 UNICODE(Universal Multiple-Octet Coded Character Set),这种编码非常大,大到可以容纳世界上任何一个文字和标志。所以只要电脑上有 UNICODE 这种编码系统,无论是全球哪种文字,只需要保存文件的时候,保存成 UNICODE 编码就可以被其他电脑正常解释。UNICODE 在很长一段时间内无法推广,直到互联网的出现,为解决 UNICODE 如何在网络上传输的问题,于是面向传输的众多 UTF(UCS Transfer Format)标准出现了。UNICODE 在网络传输中,出现了两个标准 UTF-8 和 UTF-16,分别每次传输 8 个位和 16 个位。UTF-8 顾名思义,是一套以 8 位为一个编码单位的可变长编码。在其中,每个汉字占用3个字节。于是就会有人产生疑问,UTF-8 既然能保存那么多文字、符号,为什么国内还有这么多使用 GBK 等编码的人?答案主要是历史原因,因为 UTF-8 等编码体积比较大,占电脑空间比较多,以前的电脑存储空间又很宝贵,所以如果面向的使用人群绝大部分都是中国人,用 GBK 等编码也可以。

unicode 在很长一段时间内无法推广,直到互联网的出现,为解决 unicode 如何在网络上传输的问题,于是面向传输的众多 UTF(UCS Transfer Format)标准出现了,顾名思义,UTF-8 就是每次 8 个位传输数据,而 UTF-16 就是每次 16 个位。

UTF-8 就是在互联网上使用最广的一种 unicode 的实现方式,这是为传输而设计的编码,并使编码无国界,这样就可以显示全世界上所有文化的字符了。

UTF-8 最大的一个特点,就是它是变长的编码方式。它可以使用 1~4 个字节表示一个符号,根据不同的符号而变化字节长度,当字符在 ASCII 码的范围时,就用一个字节表示,保留了 ASCII 字符一个字节的编码做为它的一部分,注意的是 unicode 里大部分中文字符的码点(分配的编码数值)用16进制数(2个字节)就可以表示,但 UTF-8 一个中文字符占 3 个字节)。从 unicode 到 utf-8 并不是直接的对应,而是要过一些算法和规则来转换。

References

[1] mailto 格式: https://www.wikiwand.com/en/Mailto
[2] ASCII: https://www.wikiwand.com/en/American_Standard_Code_for_Information_Interchange
[3] Unicode 和 UTF-8 有什么区别?: https://www.zhihu.com/question/23374078/answer/69732605

登录查看更多
8

相关内容

【实用书】学习用Python编写代码进行数据分析,103页pdf
专知会员服务
192+阅读 · 2020年6月29日
干净的数据:数据清洗入门与实践,204页pdf
专知会员服务
161+阅读 · 2020年5月14日
【实用书】Python爬虫Web抓取数据,第二版,306页pdf
专知会员服务
117+阅读 · 2020年5月10日
【电子书】大数据挖掘,Mining of Massive Datasets,附513页PDF
专知会员服务
103+阅读 · 2020年3月22日
【干货书】流畅Python,766页pdf,中英文版
专知会员服务
224+阅读 · 2020年3月22日
算法与数据结构Python,369页pdf
专知会员服务
161+阅读 · 2020年3月4日
【反馈循环自编码器】FEEDBACK RECURRENT AUTOENCODER
专知会员服务
22+阅读 · 2020年1月28日
吐血整理!140种Python标准库、第三方库和外部工具都有了
炼数成金订阅号
14+阅读 · 2019年7月30日
ISeeYou一款强大的社工工具
黑白之道
30+阅读 · 2019年5月17日
一天精通无人中级篇:遥控器协议 S-BUS
无人机
51+阅读 · 2018年12月20日
已删除
AI科技评论
4+阅读 · 2018年8月12日
干货 | 自然语言处理(5)之英文文本挖掘预处理流程
机器学习算法与Python学习
7+阅读 · 2018年4月5日
《小美好》短评文本情感分析+生成词云
数据挖掘入门与实战
5+阅读 · 2018年1月7日
教你用Python来玩跳一跳
七月在线实验室
6+阅读 · 2018年1月2日
用 Scikit-Learn 和 Pandas 学习线性回归
Python开发者
9+阅读 · 2017年9月26日
python pandas 数据处理
Python技术博文
4+阅读 · 2017年8月30日
代码这样写不止于优雅(Python版)
数说工作室
4+阅读 · 2017年7月17日
Arxiv
3+阅读 · 2019年3月1日
Arxiv
5+阅读 · 2018年10月15日
Arxiv
4+阅读 · 2018年2月13日
VIP会员
相关VIP内容
【实用书】学习用Python编写代码进行数据分析,103页pdf
专知会员服务
192+阅读 · 2020年6月29日
干净的数据:数据清洗入门与实践,204页pdf
专知会员服务
161+阅读 · 2020年5月14日
【实用书】Python爬虫Web抓取数据,第二版,306页pdf
专知会员服务
117+阅读 · 2020年5月10日
【电子书】大数据挖掘,Mining of Massive Datasets,附513页PDF
专知会员服务
103+阅读 · 2020年3月22日
【干货书】流畅Python,766页pdf,中英文版
专知会员服务
224+阅读 · 2020年3月22日
算法与数据结构Python,369页pdf
专知会员服务
161+阅读 · 2020年3月4日
【反馈循环自编码器】FEEDBACK RECURRENT AUTOENCODER
专知会员服务
22+阅读 · 2020年1月28日
相关资讯
吐血整理!140种Python标准库、第三方库和外部工具都有了
炼数成金订阅号
14+阅读 · 2019年7月30日
ISeeYou一款强大的社工工具
黑白之道
30+阅读 · 2019年5月17日
一天精通无人中级篇:遥控器协议 S-BUS
无人机
51+阅读 · 2018年12月20日
已删除
AI科技评论
4+阅读 · 2018年8月12日
干货 | 自然语言处理(5)之英文文本挖掘预处理流程
机器学习算法与Python学习
7+阅读 · 2018年4月5日
《小美好》短评文本情感分析+生成词云
数据挖掘入门与实战
5+阅读 · 2018年1月7日
教你用Python来玩跳一跳
七月在线实验室
6+阅读 · 2018年1月2日
用 Scikit-Learn 和 Pandas 学习线性回归
Python开发者
9+阅读 · 2017年9月26日
python pandas 数据处理
Python技术博文
4+阅读 · 2017年8月30日
代码这样写不止于优雅(Python版)
数说工作室
4+阅读 · 2017年7月17日
Top
微信扫码咨询专知VIP会员