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编码能节省空间

image.png

有上面的表格发现,UTF-8编码有一个额外好处,就是ASCII编码实际被看成是UTF-8一部分。


unicode与utf-8转换

在计算机的内存中,统一使用unicode编码,当保存到硬盘或者传输的时候,就转换为UTF-8编码。

下图为记事本编辑与文件的两种编码

image.png

浏览网页时,服务器会把动态生成的unicode内容转换成UTF-8在传输给浏览器

image.png

所以很多网页的源头会有类似<meta  charset="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%'.