看了好几篇编码的文章,表示还是理不顺。。仅做一些记录。
一、unicode和utf-8
unicode记录了全球的所有语言,包含了跟全球所有国家编码的映射关系。但是都用unicode来表示编码太占空间,就创建了其他的编码方案,如utf-8、gbk等。
utf-8是根据内容来动态分配字节数记录内容。使用1、2、3、4个字节表示所有字符,优先使用1个字符、无法满足则使增加一个字节,最多4个字节。英文占1个字节、欧洲语系占2个、东亚语系占3个,其它及特殊字符占4个。
二、字符的记录
要注意:
- 无论以什么编码在内存里显示字符,存到硬盘上都是2进制
- 存到硬盘上时是以何种编码存的,再从硬盘上读出来时,就必须以何种编码读(开头声明或转换),要不然就乱了
三、python中编码的转换
python中版本2和3的处理是不一样的,python3默认编码是unicode,python2默认编码是ascii码。
由此会产生一些格式类型的差异。
- python2
- python2的默认编码是ascii码,所以无法支持中文,程序若出现中文(不论是变量、赋值还是注释)就会报错。
程序中想使用中文,必须声明文件头编码,且编码要和该程序文件的编码类型一致。
如:
程序文件是utf-8编码,程序起始就添加:#-*- coding:utf-8 -*-
程序文件是gbk编码,程序起始就添加:#-*- coding:gbk -*- - python2中有两种表示字符序列的类型:str和unicode。默认的str并不是字符串,而是一个byte数组,或者可以理解成一个纯ascii码字符组成的字符串。
- 由上一点,可知python2中b开头的数组(即bytes数组)和字符串str属于同一种类型;u开头的数组则是unicode类型。可以通过函数type进行查看。
- python中,可以调用函数实现unicode和utf-8/gbk等编码的转换,方法为:
utf-8/gbk等编码的str、bytes ---> decode('原始编码') ---->unicode编码
unicode编码 --->encode('编码类型') --- >指定编码的str
写个样例,其中程序文件charset-2.py是utf-8编码,在windows环境运行,windows控制台是gbk编码显示
#-*- coding:utf-8 -*-
aaa = "你好"
bbb = b"你好"
ccc = u"你好"
print "aaa---type: ", type(aaa)," content: ", aaa
print "bbb---type: ", type(bbb)," content: ", bbb
print "ccc---type: ", type(ccc)," content: ", ccc
print "++++++++++++++++++++++++++++++++++++++++++"
aaa_decode = aaa.decode("utf-8")
bbb_decode = bbb.decode("utf-8")
print "aaa_decode---type: ", type(aaa_decode)," content: ", aaa_decode
print "bbb_decode---type: ", type(bbb_decode)," content: ", bbb_decode
aaa = aaa_decode.encode("gbk")
bbb = bbb_decode.encode("gbk")
print "aaa---type: ", type(aaa)," content: ", aaa
print "bbb---type: ", type(bbb)," content: ", bbb
print "++++++++++++++++++++++++++++++++++++++++++"
ccc_encode = ccc.encode("utf-8")
print "ccc_encode---type: ", type(ccc_encode)," content: ", ccc_encode
ccc_encode = ccc.encode("gbk")
print "ccc_encode---type: ", type(ccc_encode)," content: ", ccc_encode
在windows的输出结果:
可发现:
<1>代码7-9行,显示aaa和bbb都是str类型,ccc是unicode类型。因为程序设置的编码是utf-8,所以aaa和bbb在windows控制台无法显示,而ccc是unicode类型,支持范围比gbk更大,可以正常显示内容
<2>代码12-15行,aaa和bbb可以用decode函数转化为unicode类型,可正常显示
<3>代码17-20行,aaa_decode和bbb_decode现在是unicode编码,可以用encode转化为gbk编码,则可正常显示
<4>代码23-26,则是unicode类型的转换;转为utf-8乱码,转为gbk可以显示
- python3
- python3默认是unicode编码,支持中文,因此无需加编码头
- python3有两种表示字符序列的类型:str和bytes。
- 由2可知,u前缀的数组和无前缀的字符串,都是unicode类型;b前缀的数组是bytes,在python3中存储为ascii码,无法存储中文,即无法将中文赋值给bytes数组。
- python3中也有encode和decode,不过转成gbk、utf-8等编码是存放于bytes数组
utf-8/gbk等编码的bytes ---> decode('原始编码') ----> unicode编码,也就是python3的str
unicode编码(str) --->encode('编码类型') --- >指定编码的bytes
写个样例
aaa = "你好"
# bbb = b"你好" 直接赋值中文会报错
bbb = b"Hello"
ccc = u"你好"
print ("aaa---type: ", type(aaa)," content: ", aaa)
print ("bbb---type: ", type(bbb)," content: ", bbb)
print ("ccc---type: ", type(ccc)," content: ", ccc)
print ("++++++++++++++++++++++++++++++++++++++++++")
aaa_utf8_bytes = aaa.encode("utf-8")
aaa_gbk_bytes = aaa.encode("gbk")
print ("aaa_utf8_bytes---type: ", type(aaa_utf8_bytes)," content: ", aaa_utf8_bytes)
print ("aaa_gbk_bytes ---type: ", type(aaa_gbk_bytes)," content: ", aaa_gbk_bytes)
ccc_utf8_bytes = ccc.encode("utf-8")
ccc_gbk_bytes = ccc.encode("gbk")
print ("ccc_utf8_bytes---type: ", type(ccc_utf8_bytes)," content: ", ccc_utf8_bytes)
print ("ccc_gbk_bytes ---type: ", type(ccc_gbk_bytes)," content: ", ccc_gbk_bytes)
print ("aaa_str:", aaa_utf8_bytes.decode("utf-8"), aaa_gbk_bytes.decode("gbk"))
# print ("aaa_str:", aaa_utf8_bytes.decode("gbk"), aaa_gbk_bytes.decode("utf-8")) 编码不同会报错
print ("++++++++++++++++++++++++++++++++++++++++++")
运行结果:
可发现:
1.代码1-9行,无前缀字符串和unicode都是str类型;b前缀是bytes类型,且bytes无法直接赋值中文
2.代码12-20行,aaa和ccc通过encode进行指定字符编码,会转化成相应编码的bytes类型
3.代码22-23行,aaa相应编码的bytes类型通过decode函数可以转为unicode类型并输出,但需指定正确编码,否则会报错或解码成其它内容。
4.bbb因为是bytes类型,转换成gbk、utf-8都是一样编码和内容。
但从aaa的encode和decode变换,可知bytes无法直接赋值中文但能转换存储。
四、延伸
有个python3脚本,需读取txt文本内容,转化为gb2312编码进行处理。
执行时会提示异常,增加了errors = "ignore"参数即可。。
其中使用的函数bytes(str, "xxx_encode", errors = "ignore") 等价于encode(str, encoding="xxx_encode", errors = "ignore")函数,即把str类型转为bytes类型
with open( "./file.txt", "r", encoding="utf-8") as fp:
data=fp.read()
data_gbk_bytes= bytes(data, "gb2312", errors = "ignore")
===等价于===>
data_gb2312_bytes = data.encode("gb2312", errors = "ignore")
# str转bytes叫encode,bytes转str叫decode
# 我的理解,str和字符在python3中都是unicode编码的,encode就是将unicode的二进制内容转化为相应的编码的二进制内容
参考文章: