Unicode、GBK、UTF-8小结

来源:互联网 发布:网络导报张海亮 编辑:程序博客网 时间:2024/06/06 00:35

这几天用python写一个小程序:从一些简历里面提取有效信息,比如,电话、邮箱、公司、学校等,在中文编码上折腾了很久,下面整理一下从各个方面学到的相关知识。

零、中文编码改进的过程

1、ASCII 一开始只支持0-127之间的字符,表达英语单词足够了。

2、GB2312 开始支持中文,但只有一些常用的汉字,收录了6763个汉字。双字节编码。

3、GBK  增加到21886个汉字和图形符号。双字节编码,总体编码范围为8140-FEFE之间

4、GB18030 兼容ASCII 、GB2312和gbk,采用1、2、4多字节编码。

5、unicode 兼容所有国家不同语言字符和图形符号,一种最全面的编码方式,但本身不指定如何存放编码,utf-8是其一种存放的方式,长度可变,1~4字节,汉字占三个字节。

一、utf-8和gbk

如果要在python代码中(包括注释)用到中文,则要在首行加上

#coding:utf-8 或者 #coding:gbk

否则系统默认为ASCII编码,所能表达的字符只有0-127,无法支持中文

加上这行就可以在代码中定义中文字符串,比如

fan = "樊"

这个时候fan的len的大小取决于上行是utf-8还是gbk,长度为3和2,分别占3个和2个字节


二、decode和encode

decode是将字节解码为字符

encode刚好相反,是从字符到字节

unicodeStr = fan.decode(code); 这里的code取决于一中的首行声明,要保持一致,否则不合法


三、Unicode、GBK、UTF-8之间的转换:(假设当前coding:utf8)

unicodeStr  = fan.decode('utf-8');utf8Str     = unicodeStr.encode('utf-8');gbkStr      = unicodeStr.encode('gbk');

感觉还是一图胜百言:


1) gbk和unicode之间的转换无法通过计算得到,而需要查表获取。

2) utf-8和unicdoe之间的转换是通过计算得到,过程如下:(以“樊”为例)

unicode只表示是哪一种字符,但并不表示它怎么存放在内存中,而utf-8是它一种存放的方法,汉字占三个字节,分别以1110 10 10开头,将unicode十六个bit,按先后顺序分拆成三段拼接成24bit

0x6a 01101010

0x0a 00001010

分拆成三段为:0110 101000 001010

和1110 10 10拼接为:11100110 10101000 10001010

即为0xe6 0xa8 0x8a(如上图上所示),反过来推也是一样的。

           

3) utf和gbk不能直接转换,但是上面红色的字体却能直接执行,执行的条件是和系统的编码保持一致,默认为ASCII,可通过下面这行代码进行修改:

reload(sys)
sys.setdefaultencoding('utf-8')

这个和一中的#coding不同,上面是指定代码中的字符串以什么方式编码,这里是默认系统decode的方式。

如果当前如上所示为"utf-8",则上图中的1)是可执行的,其实并不是直接将utf-8 encode成gbk,而是先自动以系统默认的方式decode成unicode然后再encode成gbk,所以当前情况下2)是不可执行的,会提示如下错误

'utf8' codec can't decode byte 0xb7 in position 0

提示0xb7(上图中gbk的首字节)不能decode utf-8,说明在encdoe之前有对gbk按utf-8 decode成unicode,而这是不合法的。

同样,反过来,如果上面sys.setdefaultencoding('gbk'),则图中红字的2)可执行,1)会报错,原因类同。

4)BOM

Byte order mark是指在文本文件的开头有2或3个字节来表示字节序,以EF BB BF开头的字节流UTF-8编码,以FEFF或FFFE头的为unicode。

四、中文字典树

可以直接按中文的字节建树,一个汉字占树的2层或3层结点,但是在文本偏移查找时,要按汉字编码方式的长度(gbk为2,utf-8为3)进行偏移,否则为出现下面这种情况:

“男” gbk码为:0xC4 0xD0

“的需” gbk码为:0xB5 0xC4 0xD0 0xE8

这里如果按单字节偏移进字典树查找时会匹配到“男”,不仅得到是错误的结果,而且还会导致后面的解码出错(0xE8和其他字节可能不能拼装成一个合法的字符而出错)。



0 0
原创粉丝点击