一文弄懂 URLEncode 及GBK, Unicode

按: 我相信有许多程序员搞不清楚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ℴ=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 %3F a %3D 12

这样子后面的 ? 与  = 就不会被处理掉,而能够作为  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

我来评几句
登录后评论

已发表评论数()

相关站点

+订阅
热门文章