用户:Xyy23330121/Python/字符串和编码

本章将学习编码的相关信息,以及如何用 Python 生成或解决一类常见的文本乱码。

编码是计算机存储信息的方式。

bytes 对象与 bytearray 对象

编辑

bytes 对象

编辑

bytes 对象是 Python 用于表示二进制数据的对象。我们可以用b作前缀创建 bytes 对象:

a = b"abc"

此时,引号内的内容只能为 ASCII 编码中的字符。abc在 ASCII 编码中分别对应十六进制的61、62和63。所以上述例子中创建的对象,它所存储的二进制数据,用十六进制表示为 616263

由于 ASCII 编码仅有 127 个字符。因此,二进制每 8 位中,任何超出 127(即二进制的 01111111 ,或十六进制 7F )的二进制数值都需要通过转义字符来输入。比如:

a = b"\xf1"

上述例子中创建的对象,所存储的二进制数据,用十六进制表示为 f1

以上创建 bytes 对象的方法,也是用print函数输出时的输出方式。有以下示例:

a = b"a\xf1b"
print(a) #输出:b'a\xf1b'

bytes 对象支持一切不可变序列的操作。虽然 bytes 的创建和表示方法是基于 ASCII 字符的,但比起 ASCII 字符构成的字符串,bytes 对象更像是 0~255 之间整数构成的元组。如果对 bytes 对象用整数索引,会返回一个整数,而非像字符串一样返回子字符串。

bytearray 对象

编辑

上面提到过,bytes 对象的表现类似由 0~255 之间整数组成的不可变序列。而 bytearray 对象类似由 0~255 之间整数组成的可变序列。bytearray 支持一切可变序列的操作。

bytes 函数与 bytearray 函数

编辑

类似 int 函数,我们可以用 bytes([source])bytearray([source]) 创建 bytes 对象或 bytearray 对象。

其中,参数 source 可以为整数、由 0~255 之间整数组成的可迭代对象。特别的,bytes 对象和 bytearray 对象也是由 0~255 之间整数组成的可迭代对象。

  • 如果 source 为整数,则生成一个包含 source 个字节的对应实例。
  • 如果 source 为由0~255之间整数组成的可迭代对象,则将可迭代对象中的整数原封不动复制到对应位置。

十六进制字符串与 bytes 和 bytearray

编辑

bytes.fromhex 方法和 bytearray.fromhex 方法可以用表示十六进制数字的字符串创建 bytes 对象,创建时字符串不区分大小写,并且会忽略空格。比如:

value = bytes.fromhex("81f0 EA61")
print(value)   #输出:b'\x81\xf0\xeaa'

代码的输出说明,该 bytes 对象所存储的二进制数据,用十六进制表示为 81F0EA61

类似,我们还可以用 bytes.hex([sep[, bytes_per_sep]])bytearray.hex([sep[, bytes_per_sep]]) 方法创建十六进制字符串。

其中,sep 代表分隔符,默认为空字符串,即不插入分隔符。而 bytes_per_sep 代表插入分隔符的频率,默认为 1 ,即“每一个字节都插入一个分隔符”。我们有以下示例:

value = bytes.fromhex("81f0 EA61")
print(value.hex())      #输出:81f0ea61
print(value.hex(" "))   #输出:81 f0 ea 61
print(value.hex(" ",2)) #输出:81f0 ea61

bytes 和 bytearray 的方法

编辑

bytes 和 bytearray 有类似字符串的方法。参见:U:Xyy23330121/Python/bytes 和 bytearray 的方法

bytes 对象和字符的编码

编辑
常用编码列表
编码名 适用语言
utf-8 所有语言
ascii 英语
big5 中文(繁体)
gbk 中文
shift-jis 日语
utf-16 所有语言
utf-16-be 所有语言
utf-16-le 所有语言
utf-32 所有语言
utf-32-be 所有语言
utf-32-le 所有语言

字符编码 是将字符转化成二进制数据的标准。比如 & 字符,它在 ASCII 编码方式下,对应的二进制数据是 00100110 。计算机可以通过读取二进制数据,来还原出对应的字符串。常见的编码方式有 UTF-8、ASCII、UTF-16、GBK 等。

利用以下方法,我们可以把字符按编码转化成对应的bytes对象,也可以把bytes对象按编码转化成对应的字符对象。

str.encode(encoding='utf-8', errors='strict')
bytes.decode(encoding='utf-8', errors='strict')

其中,encoding表示要使用的编码,此处不区分大小写,也不区分_-。而errors表示出错时的处理方法。右表列出了几种常用编码。如果要查阅所有可用的编码名称,可以参照上面列出的文档。

以下列出几种常用的错误处理方法。如果要查阅所有可用的方法,可以参照上面列出的“错误处理方式列表”文档。

名称 说明
strict 严格模式,遇到无法解码的码位或无法编码的字符,会报错 ValueError 。
ignore 忽略错误。对于无法解码的码位或无法编码的字符,会直接跳过。
replace 在编码时,遇到无法编码的字符,就用字符 ? 代替;
在解码时,遇到无法解码的字节,就用字符 (U+FFFD)代替。

示例:常见乱码的解决

编辑

现在绝大多数计算机,在信息处理时,都默认使用了 UTF-8 等常见的编码方式。但日本的计算机不一样,一些计算机有概率在处理信息时依旧使用 Shift-JIS 编码。中文计算机在解压zip压缩文件、查阅文本文档时,如果判断文件名或文本不是 UTF-8 编码,就会自动采用 GBK 编码来解码文件。用 Shift-JIS 编码的信息被用 GBK 解码就会导致乱码。

要解决这个问题,只需要结合上面的两个操作即可。我们用以下方式解决它:

error_str = "傕傕偄傠僇儖僥僢僩 搷壺"
print(error_str.encode("GBK").decode(encoding="Shift-JIS",errors="ignore"))

从字符串创建 bytes 或 bytearray

编辑

我们上面提到过 bytes 函数和 bytearray 函数。这两个函数的完整语法为:

bytes([source[, encoding[, errors]]])

bytearray([source[, encoding[, errors]]])

只有当 source 为字符串时,encoding 参数和 errors 参数才有作用,此时 bytes(source, encoding, errors) 等同于 source.encode(encoding, errors),而 bytearray(source, encoding, errors) 等同于 bytearray(source.encode(encoding, errors))