python的unicode编码表_python学习之基础篇⼆字符编码(1)为什么要⽤字符编码
早期的计算机使⽤的是通电与否的特性的真空管,如果通电就是1,没有通电就是0,后来沿⽤⾄今我们称这种只有0/1的环境为
⼆进制制,英⽂称为binary。但是⼆进制数据(0/1)怎么能表⽰我们所熟知的英⽂,数字,字符,汉字呢?所以就有了各种编码,因
为开始计算机只在美国⽤。⼋位的字节⼀共可以组合出256(2的8次⽅)种不同的状态。(可以涵盖美国⼈使⽤的字母,数字和特殊符
号。)所以他们把其中的编号从0开始的32种状态分别规定了特殊的⽤途,⼀但终端、打印机遇上约定好的这些字节被传过来时,
就要做⼀些约定的动作:
遇上0×10, 终端就换⾏;
遇上0×07, 终端就向⼈们嘟嘟叫;
遇上0x1b, 打印机就打印反⽩的字,或者终端就⽤彩⾊显⽰字母。
他们看到这样很好,于是就把这些0×20以下的字节状态称为”控制码”。他们⼜把所有的空 格、标点符号、数字、⼤⼩写字母分
别⽤连续的字节状态表⽰,⼀直编到了第127号,这样计算机就可以⽤不同字节来存储英语的⽂字了。⼤家看到这样,都感觉很好
,于是⼤家都把这个⽅案叫做 ANSI 的”Ascii”编码(American Standard Code for Information Interchange,美国信息互换标
准代码)。当时世界上所有的计算机都⽤同样的ASCII⽅案来保存英⽂⽂字。
后来,就像建造巴⽐伦塔⼀样,世界各地都开始使⽤计算机,但是很多国家⽤的不是英⽂,他们的字母⾥有许多是ASCII⾥没
有的,为了可以在计算机保存他们的⽂字,他们决定采⽤ 127号之后的空位来表⽰这些新的字母、符号,还加⼊了很多画表格时需
要⽤下到的横线、竖线、交叉等形状,⼀直把序号编到了最后⼀个状态255。从128 到255这⼀页的字符集被称”扩展字符集“。从此
之后,贪婪的⼈类再没有新的状态可以⽤了,美帝国主义可能没有想到还有第三世界国家的⼈们也希望可以⽤到计算机吧!
等中国⼈们得到计算机时,已经没有可以利⽤的字节状态来表⽰汉字,况且有6000多个常⽤汉字需要保存呢。但是这难不倒智
慧的中国⼈民,我们不客⽓地把那些127号之后的奇异符号们直接取消掉, 规定:⼀个⼩于127的字符的意义与原来相同,但两个⼤
于127的字符连在⼀起时,就表⽰⼀个汉字,前⾯的⼀个字节(他称之为⾼字节)从0xA1⽤到0xF7,后⾯⼀个字节(低字节)从
0xA1到0xFE,这样我们就可以组合出⼤约7000多个简体汉字了。在这些编码⾥,我们还把数学符号、罗马希腊的字母、⽇⽂的假
名们都编进去了,连在 ASCII ⾥本来就有的数字、标点、字母都统统重新编了两个字节长的编码,这就是常说的”全⾓”字符,⽽原
来在127号以下的那些就叫”半⾓”字符了。中国⼈民看到这样很不错,于是就把这种汉字⽅案叫做“GB2312“。GB2312 是对 ASCII
的中⽂扩展。
因为当时各个国家都像中国这样搞出⼀套⾃⼰的编码标准,结果互相之间谁也不懂谁的编码,谁也不⽀持别⼈的编码,连⼤陆
和台湾这样只相隔了150海⾥,使⽤着同⼀种语⾔的兄弟地区,也分别采⽤了不同的 DBCS 编码⽅案——当时的中国⼈想让电脑显
⽰汉字,就必须装上⼀个”汉字系统”,专门⽤来处理汉字的显⽰、输⼊的问题,像是那个台湾的愚昧封建⼈⼠写的算命程序就必须
加装另⼀套⽀持 BIG5 编码的什么”倚天汉字系统”才可以⽤,装错了字符系统,显⽰就会乱了套!这怎么办?⽽且世界民族之林中
还有那些⼀时⽤不上电脑的穷苦⼈民,他们的⽂字⼜怎么办?真是计算机的巴⽐伦塔命题啊!
正在这时,⼤天使加百列及时出现了——⼀个叫 ISO(国际标谁化组织)的国际组织决定着⼿解决这个问题。他们采⽤的⽅法
很简单:废了所有的地区性编码⽅案,重新搞⼀个包括了地球上所有⽂化、所有字母和符号的编码!他们打算叫它”Universal
Multiple-Octet Coded Character Set”,简称 UCS, 俗称“unicode“。
unicode开始制订时,计算机的存储器容量极⼤地发展了,空间再也不成为问题了。于是 ISO 就直接规定必须⽤两个字节,也
就是16位来统⼀表⽰所有的字符,对于ASCII⾥的那些“半⾓”字符,unicode包持其原编码不变,只是将其长度由原来的8位扩展为
16位,⽽其他⽂化和语⾔的字符则全部重新统⼀编码。由于”半⾓”英⽂符号只需要⽤到低8位,所以其⾼8位永远是0,因此这种⼤
⽓的⽅案在保存英⽂⽂本时会多浪费⼀倍的空间。
这时候,从旧社会⾥⾛过来的程序员开始发现⼀个奇怪的现象:他们的 strlen函数靠不住了,⼀个汉字不再是相当于两个字符
数字转unicode编码了,⽽是⼀个!是的,从unicode开始,⽆论是半⾓的英⽂字母,还是全⾓的汉字,它们都是统⼀的”⼀个字符“!同时,也都是统⼀
的”两个字节“,请注意”字符”和”字节”两个术语的不同,“字节”是⼀个8位的物理存贮单元,⽽“字符”则是⼀个⽂化相关的符号。在
unicode中,⼀个字符就是两个字节。⼀个汉字算两个英⽂字符的时代已经快过去了。
unicode同样也不完美,这⾥就有两个的问题,⼀个是,如何才能区别unicode和ascii?计算机怎么知道三个字节表⽰⼀个符号
,⽽不是分别表⽰三个符号呢?第⼆个问题是,我们已经知道,英⽂字母只⽤⼀个字节表⽰就够了,如果unicode统⼀规定,每个
符号⽤三个或四个字节表⽰,那么每个英⽂字母前都必然有⼆到三个字节是0,这对于存储空间来说是极⼤的浪费,⽂本⽂件的⼤
⼩会因此⼤出⼆三倍,这是难以接受的。
unicode在很长⼀段时间内⽆法推⼴,直到互联⽹的出现,为解决unicode如何在⽹络上传输的问题,于是⾯向传输的众多 UTF (UCSTransfer Format)标准出现了,顾名思义,UTF-8就是每次8个位传输数据,⽽UTF-16就是每次16个位。UTF-8就是在互
联⽹上使⽤最⼴的⼀种unicode的实现⽅式,这是为传输⽽设计的编码,并使编码⽆国界,这样就可以显⽰全世界上所有⽂化的字
符了。UTF-8最⼤的⼀个特点,就是它是⼀种变长的编码⽅式。它可以使⽤1~4个字节表⽰⼀个符号,根据不同的符号⽽变化字节
长度,当字符在ASCII码的范围时,就⽤⼀个字节表⽰,保留了ASCII字符⼀个字节的编码做为它的⼀部分,注意的是unicode⼀个
中⽂字符占2个字节,⽽UTF-8⼀个中⽂字符占3个字节)。
从unicode到utf-8并不是直接的对应,⽽是要过⼀些算法和规则来转换。
7 7 E 5
0111 0111 1110 0101 ⼆进制的77E5
--------------------------
0111 011111 100101 按规则重组后的⼆进制77E5
1110XXXX 10XXXXXX 10XXXXXX 套⽤UTF-8模版(固定化模版)
11100111 10011111 10100101 代⼊模版
E 7 9
F A 5
最后简单总结⼀下:
中国⼈民通过对 ASCII 编码的中⽂扩充改造,产⽣了 GB2312 编码,可以表⽰6000多个常⽤汉字。
汉字实在是太多了,包括繁体和各种字符,于是产⽣了 GBK 编码,它包括了 GB2312 中的编码,同时扩充了很多。
中国是个多民族国家,各个民族⼏乎都有⾃⼰独⽴的语⾔系统,为了表⽰那些字符,继续把 GBK 编码扩充为 GB18030 编码。
每个国家都像中国⼀样,把⾃⼰的语⾔编码,于是出现了各种各样的编码,如果你不安装相应的编码,就⽆法解释相应编码想
表达的内容。
终于,有个叫 ISO 的组织看不下去了。他们⼀起创造了⼀种编码 UNICODE ,这种编码⾮常⼤,⼤到可以容纳世界上任何⼀
个⽂字和标志。所以只要电脑上有 UNICODE 这种编码系统,⽆论是全球哪种⽂字,只需要保存⽂件的时候,保存成 UNICODE 编
码就可以被其他电脑正常解释。
UNICODE 在⽹络传输中,出现了两个标准 UTF-8 和 UTF-16,分别每次传输 8个位和 16个位。于是就会有⼈产⽣疑问,
UTF-8 既然能保存那么多⽂字、符号,为什么国内还有这么多使⽤ GBK 等编码的⼈?因为 UTF-8 等编码体积⽐较⼤,占电脑空间⽐较多,如果⾯向的使⽤⼈绝⼤部分都是中国⼈,⽤ GBK 等编码也可以。
(2)字符在硬盘上的存储
⾸先要明确的⼀点就是,⽆论以什么编码在内存⾥显⽰字符,存到硬盘上都是2进制(0b是说明这段数字是⼆进制,0x表⽰是
16进制。0x⼏乎所有的编译器都⽀持,⽽⽀持0b的并不多)。理解这⼀点很重要。
⽐如:
ascii编码(美国):
l 0b1101100
o 0b1101111
v 0b1110110
e 0b1100101
GBK编码(中国):
⽼ 0b11000000 0b11001111
男 0b11000100 0b11010000
孩 0b10111010 0b10100010
还要注意的⼀点是:存到硬盘上时是以何种编码存的,再从硬盘上读出来时,就必须以何种编码读(开头声明或转换),要不然就乱了。
(3)编码转换
虽然有了unicode and utf-8 ,但是由于历史问题,各个国家依然在⼤量使⽤⾃⼰的编码,⽐如中国的windows,默认编码依然
是gbk,⽽不是utf-8。
基于此,如果中国的软件出⼝到美国,在美国⼈的电脑上就会显⽰乱码,因为他们没有gbk编码。
所以该怎么办呢?
还记得我们讲unicode其中⼀个功能是其包含了跟全球所有国家编码的映射关系,这时就派上⽤场了。
⽆论你以什么编码存储的数据,只要你的软件在把数据从硬盘读到内存⾥,转成unicode来显⽰,就可以了。
由于所有的系统、编程语⾔都默认⽀持unicode,那你的gbk软件放到美国电脑上,加载到内存⾥,变成了unicode,
中⽂就可以正常展⽰啦
Python3执⾏过程
1、解释器到代码⽂件,把代码字符串按⽂件头定义的编码加载到内存,转成unicode
2、把代码字符串按照语法规则进⾏解释
3、所有的变量字符都会以unicode编码声明
在py3上把你的代码以utf-8编写,保存,然后在windows上执⾏。
发现可以正常执⾏!
其实utf-8编码之所以能在windows gbk的终端下显⽰正常,是因为到了内存⾥python解释器把utf-8转成了unicode , 但是这
只是python3, 并不是所有的编程语⾔在内存⾥默认编码都是unicode,⽐如万恶的python2 就不是,它是ASCII(龟叔当初设计
Python时的⼀点缺陷),想写中⽂,就必须声明⽂件头的coding为gbk or utf-8, 声明之后,python2解释器仅以⽂件头声明的
编码去解释你的代码,加载到内存后,并不会主动帮你转为unicode,也就是说,你的⽂件编码是utf-8,加载到内存⾥,你的变
量字符串就也是utf-8, 这意味着什么?意味着,你以utf-8编码的⽂件,在windows是乱码。
其实乱是正常的,不乱才不正常,因为只有2种情况,你的windows上显⽰才不会乱。
1、字符串以GBK格式显⽰
2、字符串是unicode编码
Python2并不会⾃动的把⽂件编码转为unicode存在内存⾥。
所以我们只有⼿动转,Python3 ⾃动把⽂件编码转为unicode必定是调⽤了什么⽅法,这个⽅法就是,decode(解码) 和encode
(编码)
⽅法如下:
UTF-8/GBK --> decode 解码 --> Unicode
Unicode --> encode 编码 --> GBK / UTF-8
例如:
#!/usr/bin/env python3
#-*- coding:utf-8 -*-# write by congcong
s= '匆匆'print(s)
s1= s.decode("utf-8") # utf-8转成 Unicode,decode(解码)需要注明当前编码格式
print(s1,type(s1))
s2= s1.encode("gbk") # unicode 转成 gbk,encode(编码)需要注明⽣成的编码格式
print(s2,type(s2))
s3= s1.encode("utf-8") # unicode 转成 utf-8,encode(编码)注明⽣成的编码格式
print(s3,type(s3))
⽂件在 Python2 和 Python3 环境下运⾏结果的区别,如下所⽰:
#coding:utf-8s= "你好,中国!"print(s) # Python2输出乱码,Python3正常输出
print(type(s)) # 均输出#解码成unicode
s1= s.decode("utf-8")
print(s1) # Python2中输出 “你好,中国!”,Python3显⽰'str'对象没有属性'decode'print(type(s1)) # Python2中输出 Python3中输出 #编码成gbk 或 utf-8s2= s1.encode('gbk')
print(s2) # Python2中输出 “你好,中国!”
print(type(s2)) # Python2中输出s3= s1.encode('utf-8')
print(s3) # Python2输出乱码,
print(type(s3)) # 输出
编码相互转换的规则如下:
(4)如何验证编码转对了呢?
1、查看数据类型,python 2 ⾥有专门的unicode 类型
2、查看unicode编码映射表
unicode字符是有专门的unicode类型来判断的,但是utf-8,gbk编码的字符都是str,你如果分辨出来的当前的字符串数据是
何种编码的呢?
有⼈说可以通过字节长度判断,因为utf-8⼀个中⽂占3字节,gbk⼀个占2字节。
看输出的字节个数,也能⼤体判断是什么类型。精确的验证⼀个字符的编码呢,就是拿这些16进制的数跟编码表⾥去匹配。
关于 Unicode 与 GBK 等编码对应关系(以中⽂“路”为例):
(5)Python byte类型
把8个⼆进制⼀组称为⼀个byte,⽤16进制来表⽰。为的就是让⼈们看起来更可读。我们称之为bytes类型,即字节类型。python2的字符串其实更应该称为字节串。 通过存储⽅式就能看出来, 但python2⾥还有⼀个类型是bytes呀,难道⼜叫bytes ⼜叫字符串?
嗯 ,是的,在python2⾥,bytes == str , 其实就是⼀回事。
除此之外呢, python2⾥还有个单独的类型是unicode , 把字符串解码后,就会变成unicode。
>>>s'\xe8\xb7\xaf\xe9\xa3\x9e' #utf-8
>>> s.decode('utf-8')
u'\u8def\u98de'#unicode 在unicode编码表⾥对应的位置>>> print(s.decode('utf-8'))
路飞 #unicode 格式的字符
Python2的默认编码是ASCII码,当后来⼤家对⽀持汉字、⽇⽂、法语等语⾔的呼声越来越⾼时,Python于是准备引⼊unicode,但若直接把默认编码改成unicode的话是不现实的, 因为很多软件就是基于之前的默认编码ASCII开发的,编码⼀换
,那些软件的编码就都乱了。所以Python 2就直接搞了⼀个新的字符类型,就叫unicode类型,⽐如你想让你的中⽂在全球
所有电脑上正常显⽰,在内存⾥就得把字符串存成unicode类型。
>>> s = "路飞"
>>>s'\xe8\xb7\xaf\xe9\xa3\x9e'
>>> s2 = s.decode("utf-8")>>>s2
u'\u8def\u98de'
>>>type(s2)
注意:
Python3 除了把字符串的编码改成了unicode, 还把str 和bytes 做了明确区分, str 就是unicode格式的字符, bytes就是单纯⼆进制啦。
在py3⾥看字符,必须得是unicode编码,其它编码⼀律按bytes格式展⽰。
Python只要出现各种编码问题,⽆⾮是哪⾥的编码设置出错了
常见编码错误的原因有以下这些:
Python解释器的默认编码
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论