Python攻克之路-编码解码

字符编码
二进制
----> ASCII: 只能存英文和拉丁字符,一个字符占一个字节
----> gb2312: 只能存6700多个中文, 1980
----> gbk1.0: 存了2万多字符, 1995
----> gb18030: 2000, 27000中文
----> unicode: 万国码, 最初utf-32,一个字符占4个字符
utf-16,一个字符占2个字符或2个以上,可以存65535
utf-8,一个可变长的字符,一个英文使用ASCII码来存,一个中文占3个字节

场景分析:例如在国内程序是使用GBK编码,在日本使用JPK编码,假设日本发行的游戏到中国,但是国内的是GBK,但是他们开发时没考虑到会发展到中国,造成GBK是识别不到JPK出现乱码
方案一:在原程序上修改源代码加个中文包来支持,这种是限于重新发版本,旧的就无法实现,如果再到另一个国家也会再次出现这种情况
方案二:在各个编码间找个中间代理,无论是是那个国家的软件,在开发时都默认支持某个语言,就可以实现全部通用,在计算机里,这个中间代理语言是unicode,所以当JPK要与GBK进行沟通,JPK要先转换成unicode,这个转码的过程叫作编码(encode),国内GBK支持JPK,要从unicode转换成GBK

 

Python2
描述:默认是ASCII码,程序,运行的系统等编码都要保持一致

utf-8 --> unicode --> gbk
# -*- coding:utf-8 -*- #在开端声明使用utf-8
s = '你好'
s_to_unicode = s.decode("utf-8") #要指明原先是什么编码,否则使用Python默认的版本ACSII,这部没到gbk就可以支持中文,utf-8默认就支持中文
unicode_to_gbk = s_to_unicode.encode('gbk') #unicode是向下兼容的
print(s.decode() n) 
print(unicode_to_gbk)

注意:
unicode直接encode是节省一个decode的过程,python不会少这个过程,它知道当前的不是unicode的编码,它是不能直接encode,Python先decode,它程序没声明使用什么decode,python就会使用默认的ASCII,所以

gbk_to_unicode = unicode_to_gbk.encode("utf-8") #等于unicode_to_gbk.decode("ascii").encode("utf-8")

因此gbk到utf-8操作要先decode,再encode

gbk_to_unicode = unicode_to_gbk.decode("gbk") ##运行的环境windows是gbk
unicode_to_utf8 = gbk_to_unicode.encode("utf-8")
print(gbk_to_unicode) #中文
print(unicode_to_utf-8) #乱码

 

Python3
描述:默认是unicode,encode在编码的同时,会把数据转换顾byte类型(不同机器间的文件数据传输需要使用的),只有英文可见decode在解码时,会把bytes类型转换成字符串
b = byte = 字节类型 = [0-255]间纯数字类型

In [1]: s = 'i am 你好'
In [2]: s_to_gbk = s.encode("gbk") #s默认是unicode,所以直接编码
In [3]: print(s)
i am 你好
In [4]: print(s_to_gbk)
b'i am \xc4\xe3\xba\xc3'
In [5]: print(s_to_gbk.decode("gbk")) #转回去了
i am 你好

 编码补充

Python3数据类型: string     bytes
string: unicode
In [1]: s='hello林'               
In [2]: print(type(s))        
<class 'str'>    数据类型是str,但是存的是unicode的编码

str -->  bytes  是编码
方法一:
bytes:  16进制
描述:无论放在磁盘还是网络传输都是使用Bytes类型,bytes离底层更近
In [3]: s='hello林'
In [4]: bytes(s,'utf8')  
Out[4]: b'hello\xe6\x9e\x97' 
#16进制的内容,hello不变是因为在ACSII中与utf8是相同的,相当于h对应ACSII的内容,e对应的ACSII对应内容,到了汉字却发生变化了,
 utf8规定每个汉字占三个字节,xe6\x9e\x97这三个字节就对应林,这就是utf8规则下的bytes类型
#s是要转的参数,utf8是要转成的类型
#目标是str转成16进制的内容,也就是bytes类型,有utf8的bytes编码类型,有gbk的bytes的编码类型,每个国家都有自身一套编码类型,
 它们都是一个规则,有了这个规则utf8就把s转换成16进制,

方法二:
In [5]: s='hello林'
In [6]: s.encode('utf8')
Out[6]: b'hello\xe6\x9e\x97'

bytes ----> string   解码
方法一:
In [10]: b2=s.encode('utf8')
In [11]: str(b2,'utf8')
Out[11]: 'hello林'

方法二:
In [12]: b2=s.encode('utf8')
In [13]: b2.decode('utf8')
Out[13]: 'hello林'

gbk:
In [17]: s='hello林'
In [18]: b2=s.encode('gbk')
In [19]: b2
Out[19]: b'hello\xc1\xd6'    ##使用的是两个字节
In [20]: b2.decode('gbk')    ##对应上编码的方式
Out[20]: 'hello林'
In [21]: b2.decode('utf8')
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc1 in position 5: invalid start byte

 

posted @ 2018-03-01 09:28  Reid21  阅读(135)  评论(0编辑  收藏  举报