ASCII、GB2312、Unicode、utf8编码
ASCII讲解
因为计算机只能处理数字,如果要处理文本,就必须先把文本转换成数字才能处理。最早计算机才用比特(bit)作为一个字节,所以,一个字节表示的最大数字是255(二进制11111111=255),如果要表示更大的整数,必须用更多字节,比如连个字节65535,4个字节4294967295.。
由于计算机由美国人发明,因此最早只有127个字符被编码到计算机里,也就是大小写英文字母,数字和一些特殊符号,这个编码表被称为ASCII编码,比如大写字母A的编码65,小写字母z编码122。
GB2312由来
但是处理中文显然一个字节是不够的,至少需要两个字节,而且还不能和ASCII编码冲突,所以,中国制订了GB2312,用来把中文编写进去。针对每个国家一种编码格式,为统一一套编码unicode应运而生。
unicode讲解
unicode标准也在不断发展,最常用的就是两个字节表示一个字符串(偏僻的字符,需要4个字节),现在操作系统和大多数编程语言都支持unicode。
UTF-8由来
ASCII编码一个字节,unicode通常两个字节,即字母A用ASCII为65,二进制位01000001;unicode表示字母A需要在前面补起8个0,即00000000 01000001;至此新问题出现了,编码统一了,但是使用unicode比ASCII需要多一倍的存储空间,至此在存储和传输上就十分不划算了。所以本着节约精神,UTF-8编码诞生了,utf8把unicode字符根据不同的数字大小编码成1-6个字节,常用的英文字母编码成一个字节,汉子通常3个字节,只有很生僻的才会被编码称4-6个字节,如果传输的文本包含大量的英文字符,用UTF-8编码能节省空间
有上面的表格发现,UTF-8编码有一个额外好处,就是ASCII编码实际被看成是UTF-8一部分。
unicode与utf-8转换
在计算机的内存中,统一使用unicode编码,当保存到硬盘或者传输的时候,就转换为UTF-8编码。
下图为记事本编辑与文件的两种编码
浏览网页时,服务器会把动态生成的unicode内容转换成UTF-8在传输给浏览器
所以很多网页的源头会有类似的信息,表示该网页正是用的UTF-8编码。
字符串与数字的两个转换函数
ord()获取字符串的整数表示,chr()把编码转换为对应字符
ord('A')=65 ; ord('中')=20013;chr(66)='B';chr(25991)='文'
由于python字符串类型是str,在内存中以unicode表示,一个字符对应若干字节。如果要在网络上传输,或者保存到磁盘上,就需要把str变为字节为单位的bytes。
python对bytes类型的数据用带b前缀的单引号或双引号表示x=b'ABC',要注意'ABC'和b'ABC',前者是str,后者虽然显示一样,但是bytes的每个字符都只占用一个字节。
unicode表示的str通过encode()方法可以编码为指定的bytes,例如:
>>>'ABC'.encode('ascii')
b'ABC'
>>>'中文'.encode('utf-8')
b'\xe4\xb8\xad\xe6\x96\x87'
纯英文的str可以用ascii编码为bytes,内容一样的,含有中文的str可以用utf-8编码为bytes。含有中文的无法用ascii编码。会超出范围报错,在bytes中,无法显示为ASCII字符的字节,用\x##显示。
反过来,从硬盘上读取的字节流(bytes)要把bytes变为str,就要用decode()方法:
>>>b'ABC'.decode('ascii')
'ABC'
>>>b'\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8')
'中文'
如果bytes包含无法解码的字节,decode()会报错,如果只是一部分无效字节,可以加入参数忽略
>>>b'\xe4\xb8\xad\xff'.decode('utf-8',errors='ignore')
'中’
计算包含多少个字节方法len()函数
>>>len('ABC')
3
>>>len('中文')
2
len()函数计算的是str的字符数,如果换成bytes,len()函数就计算字符数
>>>len(b'ABC')
3
>>>len(b'\xe4\xb8\xad\xe6\x96\x87')
6
>>>len('中文'.encode('utf-8'))
6
可见一个中文字符占用三个字节
在文件加上下面以支持UTF-8编码读取
#!/usr/bin/env python3
# _*_ coding: utf-8 _*_
格式化输出两种方式
方式一
>>>'Hi, %s you have $%d.' % ('jack',1000)
'Hi,jack you have $1000.'
方式二
字符串的.format()
>>>'hello ,{0},成绩提升了{1:.1f}%'.format('小明',17.125)
'hello ,{小明},成绩提升了17.1%'.