转载:https://www.cnblogs.com/Xuuuuuu/articles/9670451.html
https://blog.csdn.net/lilong117194/article/details/83583471
一、编码介绍
ASCII
ASCII码是西欧编码的方式,采取7位编码,所以是2^7=128,共可以表示128个字符,包括34个字符,(如换行LF,回车CR等),其余94位为英文字母和标点符号及运算符号等。
GB2321
GB2312 是对 ASCII 的中文扩展。兼容ASCII。编码规定:编码小于127的字符与ASCII编码相同,特性:两个大于127的字符连在一起时,就表示一个汉字,前面的一个字节(称之为高字节)从0xA1用到0xF7,后面一个字节(低字节)从0xA1到0xFE,这样我们就可以组合出大约7000多个简体汉字了。占用字节:英文 1字节 8bit中文 2字节 16bit
GBK
GBK 兼容ASCLL 兼容 GB2312 是GB2312的扩展,但是中国的汉字太多了,我们很快就就发现有许多人的人名没有办法在这里打出来,不得不继续把 GB2312 没有用到的码位找出来用上。后来还是不够用,于是干脆不再要求低字节一定是127号之后的内码,只要第一个字节是大于127就固定表示这是一个汉字的开始,不管后面跟的是不是扩展字符集里的内容。结果扩展之后的编码方案被称为 “GBK” 标准,GBK 包括了 GB2312 的所有内容,同时又增加了近20000个新的汉字(包括繁体字)和符号。
Unicode
Unicode是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案。
目前的Unicode字符分为17组编排,0x0000至0x10FFFF,每组称为平面(Plane),而每平面拥有65536个码位,共1114112个。然而目前只用了少数平面。UTF-8、UTF-16、UTF-32都是将数字转换到程序数据的编码方案。
UTF-8
UTF-8以字节为单位对Unicode进行编码。从Unicode到UTF-8的编码方式如下:UTF-8的特点是对不同范围的字符使用不同长度的编码。对于0x00-0x7F之间的字符,UTF-8编码与ASCII编码完全相同。UTF-8编码的最大长度是6个字节。从上表可以看出,6字节模板有31个x,即可以容纳31位二进制数字。Unicode的最大码位0x7FFFFFFF也只有31位。
二、编码/解码
字符串通过编码转换成字节码,
encode:str --> bytes
字节码通过解码成为字符串
decode:bytes --> str
str = "测试"
str_utf8 = str.encode('utf-8')
str_gbk = str.encode('GBK')
print(str)
print("UTF-8 编码:", str_utf8)
print("GBK 编码:",str_gbk)
print("UTF-8 解码:", str_utf8.decode('utf-8'))
print("GBK解码:",str_gbk.decode('GBK'))
输出结果:
测试
UTF-8 编码: b'\xe6\xb5\x8b\xe8\xaf\x95'
GBK 编码: b'\xb2\xe2\xca\xd4'
UTF-8 解码: 测试
GBK解码: 测试
三、示例讲解
错误:UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd6 in position 0: invalid continuation byte
原因:当读取的文件是gbk/utf-8等编码格式,遇到这两种情况会报上面这个错误:1)python程序没有指定编码方式,取操作系统的编码方式,但操作系统编码方式与要读取的编码方式不一致;2)python程序在读取指定的文件时,程序指定的编码方式与文件的编码方式不一致;
解决方法:有两种解决方案,第二种是二进制处理,有优势:1)文件读取时指定与文件一致的编码方式;2)通过二进制读取文件,二进制写入文件,但在程序中用字符串时,需要做下编码和解码;
# -*- coding: utf-8 -*-
import os
#二进制读取,对于复制文件有优势;但是程序使用时需要通过编码、解码
with open('G:\\迅雷下载\\DOTA2Setup20200401\\test.txt','rb') as f_r:
lines = f_r.readlines()
for line in lines:
print(line.decode('gbk'))
with open('G:\\迅雷下载\\DOTA2Setup20200401\\test2.txt','wb') as f_w:
for line in lines:
f_w.write(line)
#指定文件读取方式,此时要知道文件的编码方式
with open('G:\\迅雷下载\\DOTA2Setup20200401\\test2.txt','r',encoding='utf-8') as f_r2:
lines2 = f_r2.readlines()
with open('G:\\迅雷下载\\DOTA2Setup20200401\\test3.txt','w',encoding='utf-8') as f_w2:
for line in lines2:
print(line)
f_w2.writelines(line)