一、常见编码
ASCII:ASCII 是美国信息交换标准代码。由于计算机内部的所有信息最终都是一个二进制值,而每个二进制位(bit)有两种状态,0和1,所以8个二进制位可以组合成256个状态,称为一个字节(byte)。 )。标准的 ASCII 码一共规定了 128 个字符的编码,因为只使用了最后 7 位,而且第一个统一指定为 0。之后 IBM 开发了 128 个扩展字符,不是标准的 ASCII 码,而是用于表示框架线、音标和其他欧洲非英文字母。
用128个符号来编码英文就够了,但要表示其他语言,128个符号是不够的,而且不同国家使用的字母也不同,有些国家使用的字符远不止256个。显然,ASCII 已经不够用了。问题解决了。那么有没有统一唯一的编码方式呢?答案是 Unicode。
Unicode:Unicode 是计算机科学领域的行业标准。创建 Unicode 是为了解决传统字符编码方案的局限性。它为每种语言中的每个字符设置了统一且唯一的二进制编码,以满足跨语言、跨平台的文本转换和处理的要求。
但是Unicode也有问题。比如“中”这个词的Unicode编码是16进制的4E2D,也就是二进制的100111000101101占用15位,也就是说这个符号至少需要两个字节,那么怎么知道这两个字节代表一个字符而不是两个字符分开?也就是如何区分Unicode和ASCII?
UTF-8:UTF是“Unicode Transformation Format”的缩写,可以翻译成Unicode字符集转换格式。 UTF-8 是 Internet 上使用最广泛的 Unicode 实现。其他实现包括 UTF-16(字符由两个字节或四个字节表示)和 UTF-32(字符由四个字符表示)部分表示。 UTF-8 的一个特点是它是一种可变长度编码方法。它可以用1到6个字节来表示一个符号,字节长度根据不同的符号而变化。对于一个字符的UTF-8编码,如果只有一个字节,二进制最高位为0;如果是多字节,则第一个字节从最高位开始,连续二进制位数为 1 确定编码的位数,其余字节从 10 开始。
字节数 | UTF-8编码(二进制)
1 | 0xxxxxxx
2 | 110xxxxx 10xxxxxx
3 | 1110xxxx 10xxxxxx 10xxxxxx
4 | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
5 | 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
6 | 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
很明显“中”字使用UTF-8编码需要三个字节,所以从“中”字的最后一个二进制位开始,按格式从后往前填写x,将 0 添加到额外的位。 .这样就得到了“中”字的UTF-8编码,结果为:11100100 10111000 10101101,即十六进制的E4B8AD。
二、Python3编码
Python中的编码问题困扰了我很久,尤其是Python2和Python3的区别,这里只讨论Python3中的编码问题。
Python 3 最重要的新特性可能是文本和二进制数据之间更清晰的区别。文本总是Unicode,用str类型表示,二进制数据用bytes类型表示,两者之间的转换用编码(encode)和解码(decode)实现来表示。这里可以看一下Python的官方文档:
str.encode(encoding="utf-8", errors="strict")
Return an encoded version of the string as a bytes object. Default encoding is 'utf-8'. errors may be given to
set a different error handling scheme. The default for errors is 'strict', meaning that encoding errors raise
a UnicodeError. Other possible values are 'ignore', 'replace', 'xmlcharrefreplace', 'backslashreplace' and any
other name registered via codecs.register_error(), see section Error Handlers. For a list of possible encodings,
see section Stardard Encodings.
bytes.decode(encoding="utf-8", errors="strict")
Return a string decoded from the given bytes. Default encoding is 'utf-8'. errors may be given to set a different
error handling scheme. The default for errors is 'strict', meaning that encoding errors raise a UnicodeError.
Other possible values are 'ignore', 'replace' and any other name registered via codecs.register_error(), see
section Error Handlers. For a list of possible encodings, see section Stardard Encodings.
可以看出str没有decode方法,因为是Unicode编码的,而bytes没有encode方法,而且encode和decode都是默认UTF-8编码的。当然,我们也可以使用其他方法进行编码。和解码,如:
s = "博客园"
print(s.encode())
print(s.encode("utf-16"))
print(s.encode("gbk"))
# b'\xe5\x8d\x9a\xe5\xae\xa2\xe5\x9b\xad'
# b'\xff\xfeZS\xa2[\xedV'
# b'\xb2\xa9\xbf\xcd\xd4\xb0'
那么对于一些数据,如果我们不知道它的编码格式怎么办?在Python3中,可以使用chardet模块中的detect方法查看:
import chardet
print(chardet.detect(b'\xe5\x8d\x9a\xe5\xae\xa2\xe5\x9b\xad'))
print(chardet.detect(b'\xff\xfeZS\xa2[\xedV'))
{'encoding': 'utf-8', 'confidence': 0.87625, 'language': ''}
{'encoding': 'UTF-16', 'confidence': 1.0, 'language': ''}
检测方法返回一个包含编码方法、检测到的概率和语言信息的字典。可以看出,使用chardet检测编码使用起来很简单。得到编码后,可以转换成str,方便后续处理。
三、文本编码
首先新建一个文本文档“test.txt”,内容为:“博客园博客”,然后选择“另存为”,可以看到使用的是默认的ANSI编码:
那么这个 ANSI 编码是什么?不同的国家和地区制定了不同的标准,产生了自己的编码标准如GB2312、GBK、Big5、Shift_JIS。这些使用1到4个字节来表示一个字符的各种中文扩展编码,称为ANSI编码。在简体中文Windows操作系统中,ANSI编码代表GBK编码。那么如果我们使用默认的ANSI编码,也就是GBK编码,那么在读取文本的时候会发生什么呢?
with open("test.txt", 'r') as f:
print(f.read())
# 博客园Blogs
with open("test.txt", 'r', encoding="gbk") as f:
print(f.read())
# 博客园Blogs
with open("test.txt", 'r', encoding="utf-8") as f:
print(f.read())
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb2 in position 0: invalid start byte
可以看到使用UTF-8编码时会报错,因为有无法解码的字符。那么如果我们在保存的时候使用UTF-8编码呢?
with open("test.txt", 'r') as f:
print(f.read())
# 锘垮崥瀹㈠洯Blogs
with open("test.txt", 'r', encoding="gbk") as f:
print(f.read())
# 锘垮崥瀹㈠洯Blogs
with open("test.txt", 'r', encoding="utf-8") as f:
print(f.read())
# 博客园Blogs
很明显,使用GBK编码时出现乱码。原因是编码和解码方式不一致,导致最后出现乱码。
四、URL编码
URL 是统一资源定位器(Uniform Resource Locator)。一般来说,URL只能使用英文字母、阿拉伯数字和一些标点符号,而不能使用其他文字和符号,因为网络标准RFC1738已经做出了规定。这意味着如果 URL 中有汉字,则必须对其进行编码和使用。但麻烦的是RFC1738并没有指定具体的编码方式,而是让应用程序(浏览器)来决定。
这里我们可以任意打开一个网页,比如百度百科关于编码,可以看到浏览器显示的链接没有问题:
复制一下,然后粘贴过来看看:https://baike.baidu.com/item/%E7%BC%96%E7%A0%81/80092,可以看到“encoding”这个词是自动编码的被浏览器变成“%E7%BC%96%E7%A0%81”。这里我们需要知道的是,“code”的UTF-8编码为:E7BC96,而“code”的UTF-8编码为:E7A081,所以“%E7%BC%96%E7%A0%81”是在每个单词前面加上一个“%”得到的,表示URL路径是用UTF-8编码的。
本文为原创文章,版权归知行编程网所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ 如何评论python09/23
- ♥ 如何使用python脚本实现表单打印?01/06
- ♥ 如何让python不打印转义字符串?10/15
- ♥ 如何从python中的字符串中删除非中文字符09/10
- ♥ python3库安装后无法使用怎么解决?11/21
- ♥ python判断是否大于某个值09/01
内容反馈