前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Coding】聊聊字符编码那些事儿

【Coding】聊聊字符编码那些事儿

作者头像
一名白帽的成长史
发布2019-10-13 22:42:09
1.3K0
发布2019-10-13 22:42:09
举报

Part.0

目录

目录

一、进制转换与ASCII码

  1. 进制转换
  2. 文件的存储形式
  3. ASCII码

二、Unicode和UTF-8编码

  1. 中文编码
  2. Unicode
  3. UTF编码

三、Base64编码

  1. base64
  2. 编码规则

四、URL编码

  1. URL
  2. URL编码

五、结语

Part.1

进制转换与ASCII码

进制转换

我们知道,计算机中的所有信息都是以二进制的方式表示的。

二进制数中的一个“0”或者一个“1”,大小为一个bit,又称为1位(b);

一个8位的二进制数,大小为一个Byte,又称为1字节(B)。

因此,1KB=1024B(字节)=1024*8b(位)

包括二进制在内,常用的进制表示方法如下:

  • 二进制:以0b作为前缀,0b1011。
  • 八进制:以0o作为前缀,0o174。
  • 十六进制:以0x作为前缀,0x1e。

在Python中,使用print函数输出,会自动转换为十进制数,如下:

当然,也可以使用int()函数来进行转换,不需要带前缀:

注意:被转换的数据必须以"字符串形式"输入,后面跟上所属的进制。

python内还提供了三个函数,让我们来将十进制数转换为其他进制,如下:

文件的存储形式

说完进制转换,我们再来看看文件的存储形式。

计算机中的文件,分为文本文件和二进制文件。

文本文件中存放的数据在用户读取时可以按照编码类型还原成字符形式,我们可以直接打开,如下:

二进制文件中存放的数据则不能还原成字符形式,像图片、视频、音频、可执行文件等都属于是二进制文件。

我们使用cat打开一个图片文件,由于不能还原,因此只能看到乱码:

//所以图片只能用看图软件去打开,里面的二进制数代表的是像素点。

相同的,文本文件也不可以直接执行,例如我们写好的c文本代码,必须编译成可执行的二进制文件才可以,编译完成后,直接打开就会变成乱码。

那么怎么查看二进制文件的二进制数呢?可以使用010editor等软件。例如打开上面的图片:

但是在二进制文件中,也可以插入文本信息,使用010editor直接编辑:

通过文本文件打开该文件,就可以看到我们添加的代码:

添加了代码,但图片依旧可以正常显示,图片马就是这样来的。

ASCII码

首先,ASCII码是一种字符编码方式,我们为什么要对字符进行编码呢?

字符编码就是将我们人类所使用的每一个字符都对应到一个唯一的数字上,使得我们的字符可以用二进制数的方式被计算机识别。

ASCII码,全称美国标准信息交换码,一共包含128个字符,对英文字母以及一些常用的符号进行了编码。

ASCII使得每个字符在计算机内部都对应了一个8位的二进制数,大小为1个字节。

在Linux中,使用man命令可以查看ASCII表:

//例如,字符"A"的ASCII码是65,对应八进制数101,十六进制数则是40

ASCII码中的128个字符分成了两个部分:

  • 非打印字符: 0~32,规定了一些特殊的用途, 当终端设备或者打印机遇上这些字符时, 就要做一些约定的动作,比如空格、换行等。
  • 可打印字符: 33~127,也就是可以显示输出的字符,包括了所有的大小写英文字母、数字、标点符号等。

在python2中,使用ord()函数,可以得出字符的ASCII码(十进制)

使用chr()函数,可以得出ASCII码所对应的字符:

ASCII码只包含128个字符,但随着计算机的普及,远远不能满足现有需求。

因此后续各个国家又各自对ASCII码进行了扩展,8位ASCII码只有128个字符,扩展的ASCII码又增加了128个字符。

由于每个国家扩展的内容不同,因此扩展ASCII码是一种非国际标准。

Part.2

Unicode和UTF-8编码

中文编码

前面说到,扩展ASCII码最多也只能表示128+128个字符。

然而中文的汉字量远不是ASCII码可以表示的,因此采用了新的GB2312编码来表示中文,即使用2个字节来表示一个汉字。

GB2312还对ASCII码中原有的字符也按照2个字节来重新进行编码,称为全角字符,原先的ASCII码称为半角字符。

后面在GB2312的基础之上新加了20000多个字符(包括繁体字),形成了GBK编码。

再后来在GBK的基础之上又新加了很多少数民族的字符,称为GB18030编码。

中国台湾和中国香港使用的另外一套汉字编码方案,称为BIG5码。

以上中文编码方式都是国标,非国际标准。

Unicode

我们要打开一个文本文件,必须知道它的编码方式,如果用错误的编码方式解读,就会出现乱码。

因此,国际标准化组织ISO决定废除所有的地区性编码方案,重新制订一个可以包含世界上所有文化、所有字符的编码方案,这就是Unicode编码,也称为统一码、万国码。

值得注意的几点:

  • 从2007年开始,Unicode已逐步取代ASCII成为了通用编码。
  • Python3默认采用Unicode编码,Python2默认采用ASCII码。
  • 对于英文字母和数字,ASCII和Unicode是一致的。
  • 对于汉字,ASCII码无法正常显示,因此python2开头要指定编码方式为utf-8,python3则不需要指定。
  • ord()函数在Python3中查看的是Unicode编码,不再是ASCII码了。

以“中国”为例,我们来看看Unicode的表示方法。

首先查看"中国"的Unicode十进制编码和十六进制编码:

十六进制可以写成中国

十进制可以写成中国

//使用浏览器打开,会被浏览器自动解码,显示成中文;也可以写成 \U4e2d\U56fd 和\U+4e2d\U+56fd两种方式,就不会被浏览器自动解码。

UTF编码

Unicode只是对所有的字符进行了编码,但没有规定该如何存储和传输这些字符。

比如对于Unicode编码的字母a,在计算机中该如何存储?ASCII码的话使用1个字节来进行存储,Unicode呢?

Unicode并没有规定使用几个字节,只是确定一套编码方式。

还需要使用UTF编码(Unicode Transformation Format)来存储,即Unicode的转换格式。

UTF包含UTF-8、UTF-16、UTF-32。

以UTF-8为例:

  • UTF-8是一种可变长的编码方式,使用1~6个字节表示一个符号。
  • 英文字母被编码成1个字节,汉字通常是3个字节,生僻字符被编码成4~6个字节。
  • 动态的编码方式可以有效减小存储所占的空间。
  • 如果字节的第一位是0,则这个字节单独就是一个字符;
  • 如果字节的第一位是1,连续有多少个1,就表示字符占用多少个字节。

如图,UTF-8就是Unicode的一种实现方式,当数据在计算机内存中被处理时,统一使用Unicode编码。当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编码。

Part.3

Base64编码

Base64

ASCII码是把字符转换为二进制数,Base64则是把二进制数编码成字符。

Base64编码的作用:

  • 某些系统中只能使用ASCII字符,Base64是将非ASCII字符的数据转换成ASCII字符的一种方法。
  • 在ASCII码中有很多不可见的控制字符,这些控制字符不利于在网上传输,Base64只使用了ASCII码中一部分可见字符。
  • Base64包括大小写字母各26个、10个数字、加号+、斜杠/,一共64个字符。
  • 除了这64个字符之外,在Base64编码中可能还会使用等号=作为后缀填充,因为base64编码后的字符长度必须为4的倍数。

编码规则

Base64编码要求把3个8位字节(3*8=24)转换为4个6位的字节(4*6=24),之后在6位的前面补两个0,形成8位一个字节的形式。

如果剩下的字符不足3个字节,则用0填充,输出字符使用"="号,因此文本末尾可能出现"="号。

根据编码表进行转换,Base64有自己的编码表:

以 s13为例,进行base64编码:

  • 转换为ASCII码:115 49 51
  • 转换为二进制格式:01110011 00110001 00110011
  • 重新分为4组:011100 110011 000100 110011
  • 开头补0转换为十进制:28 51 4 51
  • 根据编码表得到base64编码:c z E z

如何确定一个字符串是否是base64编码呢?

  • 字符串只可能包含A-Z,a-z,0-9,+,/,=字符。
  • =只会出现在字符串最后,最多三个,当然也可能没有。
  • 字符个数是4的倍数。

在linux中快速编码(-n表示不添加换行符):

在linux中解码:

使用python2编码:

使用python2解码:

使用python3编码(加b表示bytes类型):

使用python3解码:

base64对二进制数进行编码,因此主要处理对象是二进制文件,对文件进行编码:

还原文件需要用一些在线转换工具,也可以直接粘贴到浏览器中,加上识别头部:

Base编码除了base64以外,还有其他的如下:

  • Base16:由0~9、A~F组成,实际上就是十六进制数。
  • Base32:由大写字母、234567组成。
  • Base85:由0-9、A-Z、a-z、以及23个字符组成:!#$%&()*+-;?@^_`{|}~

Part.4

URL编码

URL

URL(Uniform Resource Locator,统一资源定位符)是一种可以为互联网中所有资源进行统一定位的机制。

常见格式:

协议名://主机名(IP地址):端口/路径?请求

?参数名1=参数值1&参数名2=参数值2,可以通过Get方式传参,如下:

向后端传递user=admin,passwd=admin

URL编码

我们为什么需要URL编码呢?

试想一下,如果要传输的参数值中包含“=”或“&”这种特殊字符该怎么办?

解决方法就是使用URL编码。

URL编码格式:%十六进制ASCII码

例如&的URL编码就是%26,通过编码传递&符:

并不是所有字符都需要URL编码,规则如下:

  • 传输标准ASCII字符无需URL编码,传输容易引起歧义的字符时,就要进行URL编码。
  • 如果在URL中对一些ASCII标准字符进行了URL编码,那么浏览器会自动将其解码。
  • 特殊字符浏览器不会进行自动解码。
  • 如果要在URL中传送中文,也必须要经过URL编码。
  • +比较特殊,它在URL中会被视为空格。

有办法绕过浏览器的自动解码呢?

答案是:可以对字符进行二次URL编码。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-10-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 一名白帽的成长史 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档