编码与解码
首先,明确一点,计算机中存储的信息都是二进制的

编码/解码本质上是一种映射(对应关系):
比如‘a’用ascii编码则是65,计算机中存储的就是00110101,但是显示的时候不能显示00110101,还是要显示'a',

但计算机怎么知道00110101是'a'呢,这就需要解码,当选择用ascii解码时,当计算机读到00110101时就到对应的ascii表里查看发现是'a',就显示为'a'

编码(encode):文本字符与二进制串的对应关系,文本字符 ——> 二进制串
解码(decode):二进制串与文本字符的对应关系,二进制串 ——> 文本字符


1.为了处理英文字符,产生了ASCII码
2.为了处理中文字符,产生了GB2312
3.为了处理各国字符,产生了Unicode
4.为了提高Unicode存储和传输性能,产生了UTF-8,它是Unicode的一种实现形式

 


ASCII & UTF-8
大家熟知的ASCII以1字节(8个bit)表示一个字符,首位全是0,表示的字符集明显不够用

unicode编码系统是为表达任意语言而设计的,为了防止存储上的冗余(比如,对应ascii码的部分),其采用了变长编码,
但变长编码给解码带来了困难,无法判断是几个字节表示一个字符.

UTF-8是针对unicode变长编码设计的一种前缀码,根据前缀可判断是几个字节表示一个字符

Unicode符号范围 | UTF-8编码方式
0000 0000 ~ 0000 007F | 0xxx xxxx
0000 0080 ~ 0000 07FF | 110x xxxx 10xx xxxx
0000 0800 ~ 0000 FFFF | 1110 xxxx 10xx xxxx 10xx xxxx
0001 0000 ~ 0010 FFFF | 1111 0xxx 1110 xxxx 10xx xxxx 10xx xxxx


如果一个字节的第一位是0,则这个字节单独就是一个字符;
如果第一位是1,则连续有多少个1,就表示当前字符占用多少个字节。


比如"严"的unicode是4E25(100111000100101),4E25处在第三行的范围内(0000 0800 ~ 0000 FFFF),
因此"严"的UTF-8编码需要三个字节,即格式是"1110xxxx 10xxxxxx 10xxxxxx"。
然后,从"严"的最后一个二进制位开始,依次从后向前填入格式中的x,高位补0:

1110xxxx 10xxxxxx 10xxxxxx
0100 111000 100101 #最前面补一个0
11100100 10111000 10100101

得到"严"的UTF-8编码是"11100100 10111000 10100101"。

 


python中的解码和编码

在python中,编码解码其实是不同编码系统间的转换!!!!
默认情况下,转换目标是Unicode,即编码unicode —— >str,解码str ——> unicode,其中str指的是字节流

而str.decode是将字节流str按给定的解码方式解码,并转换成utf-8形式,
u.encode是将unicode类按给定的编码方式转换成字节流str

注意:
调用encode方法的是unicode对象生成的是字节流,即编码
调用decode方法的是str对象(字节流)生成的是unicode对象,即解码

若str对象调用encode会默认先按系统默认编码方式decode成unicode对象再encode,忽视了中间默认的decode往往导致报错!!!!!

简单的来说:
decode()方法将其他编码字符转化为Unicode编码字符
encode()方法将Unicode编码字符转化为其他编码字符


在Python中有两个和字符很相关的类型: 一个是str类型,一个是unicode类型

这两种类型的对象都是sequece序列,其中str是字节序列,而unicode是字符序列

decode的作用是将其他编码的字符串转换成unicode编码,如str1.decode('gb2312'),表示将gb2312编码的字符串str1转换成unicode编码。
encode的作用是将unicode编码转换成其他编码的字符串,如str2.encode('gb2312'),表示将unicode编码的字符串str2转换成gb2312编码。

 

 


示例如下:
>>> a = '中国'
>>> a
'\xe4\xb8\xad\xe5\x9b\xbd' #可以看出a是utf-8编码(每个汉字占3个字节)
>>> b = a.decode('utf-8') #将utf-8编码的字符转换(解码)为Unicode编码
>>> b
u'\u4e2d\u56fd' #可以看出b是Unicode编码的字符串,最前面有字符u
>>> c = b.encode('gbk') #将Unicode编码的字符,转换(编码)为gbk编码
>>> c
'\xd6\xd0\xb9\xfa' #gbk编码的字符串每个汉字占用2个字节

>>> d = a.encode('gb2312') #直接将utf-8编码的字符转换为gb2312编码,报错
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)
>>>

由上述可知,decode()方法可以将任何编码的字符,转换为Unicode编码
而如果想从编码1转换为编码2,必须先将编码1转换(解码)为Unicode编码,然后才能转换(编码)为编码2 (针对python 2.x)

 


python2.7中的字符串:

unicode ——》编码encode('utf-8') ——》写入文件

读出文件 ——》解码decode('utf-8') ——》unicode


在使用unicode的时候,必须注意以下的原则:

1、程序中出现字符串的地方加前缀u,表示为unicode类型

2、不要使用str函数,在使用的时候使用unicode函数

3、不要使用string模块

4、只有在写入文件或者数据库或者网络的时候,才使用encode函数来进行编码发送;只有在把数据读取回来的时候,才使用decode进行解码


在使用读写unicode数据库的时候,注意几个方面:

1、数据库服务器,例如mysql,只要每个表使用utf-8格式来进行编码即可

2、数据库适配器,例如mysqldb,在connect()方法中使用use_unicode方法

3、web开发框架,例如django,进行更多的设置

 


自己写代码时只需记住str字节流调用decode,unicode对象调用!!!!!


s = u'严' #定义了一个unicode对象(不是utf8)
s #输出u'\u4e25'
print type(s), s #输出<type 'unicode'> 严


u = s.encode('utf8') #用s.encode('utf8'),则将s使用utf-8编码并将编码结果保存为字节流
u #输出'\xe4\xb8\xa5'
print type(u),u #输出<type 'str'> 涓

 

还有要注意的是,终端默认的编码格式是gbk,windows cmd中可以通过chcp查看以及改变,也可以到注册表修改终端默认编码(HKEY_CURRENT_USER console或者powershell下的codepage),936为简体中文,65001为utf8,两者都可显示中文,但为了方便中文输入,我将其默认设为936


当调用print函数将内容格式化输出到终端时,会将unicode对象转换为终端的编码方式输出 !!!!!
如上面第一次print的结果是正常的,print utf8字节流时,终端按其默认gbk解码显示时就会出问题,这里恰巧'\xe4\xb8'为gbk下的“涓”

t = s.encode('utf8').decode('utf8')
t #输出u'\u4e25'


文件的编码格式
保存文本时也有编码格式,比如txt文件保存可选择则ASCII、utf8等,对py文件可在前两行注明编码方式# -*- coding: UTF-8 -*-

在python中读取文件
fr = open('encode.py','r')
fstr = fr.read()

只要记住fstr是字节流,其他的操作参看上面即可

注:以上操作均在cmd或powershell下完成,在python自带的解释器下会有问题,s=u'你好',然后s,显示的虽然是unicode对象,但是编码却是gbk的而不是unicode

posted on 2018-09-04 23:53  苦咖啡~~  阅读(419)  评论(0编辑  收藏  举报