字符编码和python使用encode,decode转换utf-8, gbk, gb2312的问题

时间:2021-10-05 11:04:07

ASCII码

标准ASCII码使用7位二进制数(前128个ASCII码),表示大写或小写字母、数字0到9、标点符号以及在美式英语中使用的特殊控制字符。

在标准ASCII码中,最高位(b7)用作奇偶校验位,所谓奇偶校验,是指在代码传送过程中用来检验是否出现错误的一种方法,一般分奇校验和偶校验两种。奇校验规定:在正确代码的一个字节中1的个数必须是奇数,若非奇数,则在最高位b7位添1;偶校验规定:在正确代码一个字节中1的个数必须是偶数,若非偶数,则将最高位b7位置1。

后128个称为扩展ASCII码。许多基于x86的系统都支持使用扩展(或“高”)ASCII。扩展ASCII 码允许将每个字符的第8位用于确定附加的128 个特殊符号字符、外来语字母、图形符号等。

常见的ASCII码的值为:

换行LF为0x0A,回车CR为0x0D,空格为0x20,'0'为0x30,‘A’为0x41,'a'为0x61

查询ASCII技巧,方便查询ASCII码对应的字符:新建一个文本文档,按住ALT+要查询的码值(注意,这里是十进制),松开即可显示出对应字符。例如:按住ALT+97,则会显示出'a'。

扩展ASCII码

扩展ASCII码是从128-255的字符。

Unicode编码

注意:Unicode只是一个符号集,它规定了符号的二进制代码,却没有规定二进制代码如何存储。

一般所称的Unicode编码指的是UCS编码方式,即直接存入符号的Unicode二进制代码。

UTF-8编码

UTF-8是互联网上最广泛使用的一种Unicode的实现方式。

UTF-8是一种变长的编码方式,它使用1-4个字节表示一个符号,根据不同的符号选择不同长度的字节表示。

UTF-8的编码规则很简单,只有二条:

1)对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。

2)对于n字节的符号(n>1),第一个字节(注意:1个字节表示8位二进制数)的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。

Unicode符号范围(16进制) UTF-8编码方式(2进制)
0000 0000-0000 007F 0xxxxxxx
0000 0080-0000 07FF 110xxxxx 10xxxxxx
0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

跟据上表,解读UTF-8编码非常简单。如果一个字节的第一位是0,则这个字节单独就是一个字符;如果第一位是1,则连续有多少个1,就表示当前字符占用多少个字节。

Unicode与UTF-8的转换方式:

在Windows系统最简单的方式是采用记事本打开文档然后选择编码方式另存为。

解决python乱码问题

字符串在python的内部采用unicode的编码方式,因此,在做编码转换时,通常需要以unicode作为中间编码,即先将其他编码的字符串解码(decode)成unicode,再从unicode编码(encode)成另一种编码。 编码是一种用二进制数据表示抽象字符的方式,utf8是一种编码方式。

代码中的字符串编码默认和代码文件编码相同。

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

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

因此,转码的时候一定要先搞明白,字符串str是什么编码,然后decode成unicode,然后再encode成其他编码


python2中的unicode和python3中的str等价。可以查看s.__class__,如果为<class 'str'>则为unicode编码及文本数据,如果为<class 'bytes'>则为utf8编码及二进制数据。str(s, 'utf8')和s.decode('utf8')等价。

如果字符串在代码中被定义为s=u'中文',则s就是python内部编码unicode。

unicode类型再解码会报错。

判断一个字符串是否为unicode方法isinstance(s, unicode),python2中的unicode和python3中的str等价,所以在python3中判断一个字符串是否为unicode方法为isinstance(s, str)。

获取系统默认编码:

import sys
print(sys.getdefaultencoding())

有些IDE输出乱码是因为控制台不能输出字符串的编码,这倒不是程序本身的问题。比如windows的控制台是gb2312编码方式,则utf8的输出格式不能正确输出。

一种输出格式为gb2312避免乱码的方式(如果不确定是哪种编码格式,可以使用一下的通用形式去处理):

字符编码和python使用encode,decode转换utf-8, gbk, gb2312的问题
 1 #coding=utf-8
2
3 s='中文'
4
5
6 if(isinstance(s, str)):
7 #s为u'中文'
8 s.encode('gb2312')
9 else:
10 #s为'中文'
11 s.decode('utf8').encode('gb2312')
字符编码和python使用encode,decode转换utf-8, gbk, gb2312的问题

采用标准库codecs模块

codecs.open(filename, mode='r', encoding=None, errors='strict', buffering=1)
1 import codecs
2 f = codecs.open(filename, encoding='utf-8')

使用上边这种方式读进来utf-8文件,会自动转换为unicode。但必须明确该文件类型为utf8类型。如果是文件中有汉字,不是一个字节一个字节地读而是整个汉字的所有字节读进来然后转换成unicode(猜想跟汉字的utf8编码有关)。

下边的代码也是一种使用codecs的读写方式

字符编码和python使用encode,decode转换utf-8, gbk, gb2312的问题
#coding=utf-8
import codecs

fin
= open("test.txt", 'r')
fout
= open("utf8.txt", 'w')

reader
= codecs.getreader('gbk')(fin)
writer
= codecs.getwriter('gbk')(fout)

data
= reader.read(10)
#10是最大字节数,默认值为-1表示尽可能大。可以避免一次处理大量数据
while data:
writer.write(data)

data = reader.read(10)