(2)字符编码关系和转换(bytes类型)
ASCII 占一个字节,只支持英文
GB2312 占2个字节,只支持6700+汉字
GBK 是GB2312的升级版,支持21000+汉字
Shift-JIS 日本字符编码
ks_c-5601-1987 韩国字符编码
TIS-620 泰国编码
unicode 2-4个字节,兼容万国编码,对于汉字收录136690个,还在增加中...
UTF-8 使用1,2,3,4个字节表示字符
关于unicode万国字符
1、直接支持全球所有语言,每个国家都可以不再使用自己之前的旧编码了
2、包含了跟全球所有国家编码的映射关系
unicode解决了字符和二进制的对应关系,但是使用unicode表示一个字符,太浪费空间(比如表示Python这个单词,需要12个字节才能表示,比原来ASCII表示增加了一倍的字节)
PS:目前计算机的内存容量普遍都很大,对于内存占用,硬件几乎不是问题,但是网络的传输是一个非常复杂的环境,局限性比较大,而且网络传输的数据量非常大,如果增加一倍将会可能影响传输效率
关于UTF-8
为了解决unicode的缺陷,即存储过大和网络传输时的问题,出现了UTF-8(Unicode Transformation Format)编码方案,即unicode中的编码进行转换,以便于在存储和网络传输时可以节省空间
优先使用1个字符,无法满足再增加一个字符,属于一种优化机制,最多4个字节(英文占1个字节、欧洲语系占2个字节、东亚占3个字节、其他以及特殊字符占4个字节)
还有UTF-16和UTF-31编码
UTF-16 使用2、4个字节,优先使用2个字节,否则使用个字节
UTF-32 使用4个字节表示所有字符
PS:UTF是为unicode编码设计的一种在存储和传输时节省空间的编码方案
基于目前的现状,内存中的编码固定就是unicode(万国编码,兼容万国字符)
在存入磁盘时,需要将unicode转成一种更为精准的格式,utf-8:全称Unicode Transformation Format,将数据量控制到最精简
在读入内存时,需要将utf-8转成unicode
PS:所以我们需要明确:内存中用unicode是为了兼容万国软件,即便是硬盘中有各国编码编写的软件,unicode也有相对应的映射关系
关于乱码
存文件时用utf-8编码,保证兼容万国,不会乱码,而读文件时选择了错误的解码方式,比如gbk,则在读阶段发生乱码,读阶段发生乱码是可以解决的,选对正确的解码方式就ok了
保证不乱吗的核心法则就是,字符按照什么标准而编码的,就要按照什么标准解码,此处的标准指的就是字符编码
在内存中写的所有字符,一视同仁,都是unicode编码,比如我们打开编辑器,输入一个“你”,我们并不能说“你”就是一个汉字,此时它仅仅只是一个符号,该符号可能很多国家都在使用,根据我们使用的输入法不同这个字的样式可能也不太一样。只有在我们往硬盘保存或者
基于网络传输时,才能确定”你“到底是一个汉字,还是一个日本字,这就是unicode转换成其他编码格式的过程了
PS:存到硬盘上的是什么编码的文件,再从硬盘上读取时,就必须以存储时的编码标准去读,不然就乱码
PS:如果编码时候的字符是一种国家语言,保存时候用的是不相对应的编码,如果文档关闭后,则再打开保存后的文档就是乱码,无法修复 *****必须要注意的
python中设定编码
#coding:utf-8,python中写在第一行,就是用来决定以什么编码格式来读入内存,这一行就是来设定python解释器这个软件的编码使用的编码格式这个编码
可以用sys.getdefaultencoding()查看
PS:如果不在python文件指定头信息#-*-coding:utf-8-*-,那么python2中默认使用ascii,python3中默认使用utf-8
对于print需要特别说明的是:
当程序执行时,比如
x='上' #gbk下,字符串存放为\xc9\xcf
print(x) #这一步是将x指向的那块新的内存空间(非代码所在的内存空间)中的内存,打印到终端,按理说应该是存的什么就打印什么,但打印\xc9\xcf,对一些不熟知python编码的程序员,立马就懵逼了,所以龟叔自作主张,在print(x)时,使用终端的编码格式,将内存中的\xc9\xcf转成字符显示,此时就需要终端编码必须为gbk,否则无法正常显示原内容:上
什么是字符编码
字符编码:把字符转换成(编码)计算机能识别的数字
解码:把计算机能识别的数字转换成人类能识别的字符
在编码与解码的过程中一定要遵循一个字符与数字一一对应关系的标准,
该标准称之为字符编码表
ASCII:用8bit(1Bytes)表示一个英文字符
1Bytes=8bit
1KB=1024Bytes
1MB=1024KB
1GB=1024MB
1TB=1024GB
1PB=1024TB
GBK:2Bytes表示一个中文字符,1Bytes表示英文字符
unicode: 2Bytes表示一个字符
编码的转换
Python3会自动将编码在内存中转换成unicode,Python2则不会
Python2中我们将文件头声明成UTG-8的编码,加载到内存并不会像Python3一样去自动转换,文件编码是UTF-8则加载到内存里,变量字符串也是UTF-8,这时候在win系统打开编码的文件,则是乱码既然Python2并不会自动把文件编码转换成unicode放入内存,那么我们只能自己转,使用decode(解码)和encode(编码)
unicode的二进制------------>encode------------>utf-8格式的二进制(编码)
unicode的二进制<------------decode------------utf-8格式的二进制(解码)
例:test.py(没有解码直接读取内存)
#coding: utf-8
s = '中文字符'
print(s)
这时候在CMD窗口下用Python3打开文件是不会乱码的,因为自动转换unicode编码,但是Python2则直接显示乱码
PS:读入内存时候需要解码(decode),则从内存中读取保存时候需要编码(encode)
例:test.py(编码与编码之间的转换)
#coding: utf-8
s = '中文字符' #中文肯定是GBK编码
s2 = s.decode('utf-8') # 这里将s这个变量解码成UTF-8
s3 = s2.encode('GBK') #然后将s2编码成GBK
print(s2)
PS:因此,转码的时候一定要先搞明白,字符串str是什么编码,然后decode成unicode(即UTF-8),然后再encode(编码)成其他编码
PS:切记编码之间不能直接转,否则乱码和造成不可逆的文本损坏导致千百万行代码损毁
代码中字符串的默认编码与代码文件本身的编码一致
如:s='中文'
如果是在utf8的文件中,该字符串就是utf8编码,如果是在gb2312的文件中,则其编码为gb2312。这种情况下,要进行编码转换,都需要先用decode方法将其转换成unicode编码,再使用encode方法将其转换成其他编码。通常,在没有指定特定的编码方式时,都是使用的系统默认编码创建的代码文件。
如果字符串是这样定义:s=u'中文',则该字符串的编码就被指定为unicode了,即python的内部编码,而与代码文件本身的编码无关。因此,对于这种情况做编码转换,只需要直接使用encode方法将其转换成指定编码即可。
PS:如果一个字符串已经是unicode了,再进行解码则将出错
对其编码方式是否为unicode进行判断
isinstance(s,unicode) #用来判断是否为unicode
用非unicode编码形式的str来encode会报错,如何获得系统的默认编码?
#!/usr/bin/env python
#coding=utf-8
import
sys
printsys.getdefaultencoding()
该段程序在英文WindowsXP上输出为:ascii
该段程序在英文Windows7上输出为:mbcs
在某些IDE中,字符串的输出总是出现乱码,甚至错误,其实是由于IDE的结果输出控制台自身不能显示字符串的编码,而不是程序本身的问题。
如在UliPad中运行如下代码:
s=u"中文"
print s
会提示:UnicodeEncodeError:'ascii' codec can't encode characters in position 0-1: ordinal notinrange(128)。这是因为UliPad在英文WindowsXP上的控制台信息输出窗口是按照ascii编码输出的(英文系统的默认编码是ascii),而上面代码中的字符串是Unicode编码的,所以输出时产生了错误。
将最后一句改为:prints.encode('GBK')
则能正确输出“中文”两个字。
若最后一句改为:prints.encode('utf8')
则输出:\xe4\xb8\xad\xe6\x96\x87,这是控制台信息输出窗口按照ascii编码输出utf8编码的字符串的结果。
unicode(str,'gb2312')与str.decode('gb2312')是一样的,都是将gb2312编码的str转为unicode编码
使用str.__class__可以查看str的编码形式
注意事项:
1、保证文本文件不乱码的核心是存取采用同一种编码标准,就是在什么在编写的时候是什么语言,就要保存对应的语言标准格式存(如在编写的时候用的是日文,而保存时候用的是GBK中文编码,则下次打开时无论用何种编码都是乱码无法修复,要特别注意)
2、python3解释器读文件默认编码为utf-8
3、python2解释器读文件默认编码为ASCII
4、#coding:编码,在文件头指定编码的时候,如果打开的是其他编码的文件,则保存运行时候会乱码。打开的是什么编码的文件指定文件头编码也需要对应标准
PS:可以指定文件头来修改解释器默认读取文件内容的编码
bytes类型
bytes类型就是字节类型
把8个二进制一组称为一个byte,用16进制来表示
Python2里面字符串其实更应该称为字节串,但是python2里面有一个类型是butes,所以在Python2里面bytes == str(即bytes类型就等于字符串类型)
在Python2里面还有个单独的类型是unicode,把字符串解码后,就会变成nuicode
# coding: utf-8
s = '中文字符'
s2 = s.decode('utf-8')
print(type(s2))