unicode编码表_关于编码

编码实质就是0101序列翻译成我们人类能够看懂的东西

========================

ASCII 用后7位 最后一位保留了 总共128种字符

ASCII的扩展(EASCII):使用了最高位,扩展到256种,但是各国都有自己的标准

于是有了ISO/8859-1 重新定义了 160~255个字节

因为一个字节只能使用256个字符,对于亚洲国家来说不够

于是有了GB2312的双字节编码(2^16=65536种),又因为罕见字和繁体字没办法处理

于是有了GBK

各个国家的编码方式的不同,于是出现了Unicode

但是如果unicode以固定的长度存储,将会大大的浪费带宽和存储空间

于是出现了可变长的存储方案,UTF-8,UTF-16

如何表示unicode的编码,

比如“汉”是U+6C49,实质也是0101序列,那么如何翻译呢?

类比,unicode就像英语,然后各个国家翻译成自己的语言

各个国家表示的就是UTF-8,UTF-16等等,每种都有自己的翻译,然后对照Unicode表

Unicode用4个字节,表示了40多亿个字符(2^32),同时规定了和其他编码的映射关系,

所有的操作系统都支持Unicode,所有存到内存中的0101序列都是由Unicode来存储的。

比如和UTF-8的(翻译方式):

fb20f632148312657e02e607e927a926.png

为了更好理解,上面这张表对应Unicode的范围转换成10进制:

0-127:---第一行

128-2047:---第二行

2048-65535:---第三行

65536-1114111 ---第四行

比如”好”对应的Unicode编码是597D,十进制为22909,对应的区间落在第三行,所以使用3个字节,

597D二进制表现为0101 1001 0111 1101

填充到第三行: 1110 0101 1010 0101 1011 1101

十六进制: e 5 a 5 b d

c4b8f980a5058f7f07aa43e90b9862dd.png

这里和a.encode(‘utf-8’)结果是一样的

所以当我们看见类型这样的字节时候应该这样反应(python3中使用utf-8):

这个例子是三个字节,对应格式是:1110xxxx 10xxxxxx 10xxxxxx

首先全部转化成二进制,剔除固定格式中的0101,只留下x,这个x组成的就是utf-8对应的unicode

UTF-8的编码规则:对于一个字节,直接是使用ASCII

对于需要N个字节的,第一个字节的前N为置为1,N+1位置为0,后边的每一个字节的前两位都置为10

结合到实际我们是如何使用UTF-8存储文件的,我们规定了一个文件hello.txt,编码使用UTF-8,内容只有“您好”两个字,首先查询Unicode的表结合UTF-8的规则,和上边一样对应的求出一串的0101001,同理“好”也是这样,这样就会以010100..的方式存储起来了。

在我们查看这个文件的时候,其实就是从内存中加载(一连串的0101001..),然后显示到屏幕上,因为原来我们是用UTF-8形式的01010存储起来的,那么读取的时候,应该使用UTF-8的规则去读取,如果用GBK或者别的规则去读取,就会乱码。

因为是一连串的0101,如何判断一个字符的分割?(假设已经知道他是UTF-8编码)

因为之前提到UTF-8的规则,N字节就设置前N为1,N+1为置为0,加载的时候以字节为单位(8位),比如加载了一个0xxxxx,我们就知道他占用一个字节,继续读取读到1110xxxx这样形式的,那么后边的两个字节会和这个组成一个翻译单元,去Unicode表中找到对应的字。这样就可以显示出来了

存储的过程实质就是将这个文件用二进制的形式存到硬盘上,那么如何编码这些010101,是由我们采用的编码来确定的。因为Unicode使用4个字节,可以表示所有的文字,

假设我们存储“你好”这个文本,对应unicode是u4f60u597d,他实际的存储空间就是8个字节(64位),

但是实际上,不会用这种方式来存储,很浪费空间。如果我们使用UTF-8表做下映射,可以减少存储空间,4f60对应十进制的20320,也是落在第三区间,因此使用3个字节,参考上面我们可以得出他用十六进制的编码为:

7f329372b0b6dab706183524b89a89e9.png

注意到 这样3个事实,

1。Unicode必须要用4个字节,因此前边要置为0

2。00 00 4f 60 00 00 59 7d 和 e4 bd a0 e5 a5 bd所表示的二进制是不一样的!

3。读取的时候,实际读取的是e4 bd a0 e5 a5 bd所表示的二进制字符流,操作系统事先知道了他使用了UTF-8编码,所以能够用UTF8的规则来读取。

比如:e二进制是:1110 ,那么接下来他会读取3个字节,e4 bd a0,转为2进制,去除第一个字节的1110,第二和第三个字节的10,能够得到另外的2进制串,

e4 bd a0 --->‭1110 0100 1011 1101 1010 0000‬ --->0100 1111 0110 0000-->4F60

这个4F60在Unicode表中对应的就是“你”,操作系统默认有一张Unicode表可供查询

241f477f833bb45a0b53cd1771e0c969.png

cdfbe9e864418002ec0a25d673075221.png

本文参考了许多知乎上的回答:

Python 编码为什么那么蛋疼? - 刘志军的回答 - 知乎

Python 编码为什么那么蛋疼?​www.zhihu.com
6d8f8700291d13c53483a4cbfc5ad8e9.png

Python 编码为什么那么蛋疼? - Alex-金角大王的回答 - 知乎

Python 编码为什么那么蛋疼?​www.zhihu.com
1127bf457ae1f6befc2526625511ff66.png

本人小白一枚, 如果错啦,请大神指出,谢谢啦~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值