第4章--文本和字节序列

第4章–文本和字节序列

本章将讨论下述话题:
• 字符、码位和字节表述
• bytes、bytearray 和 memoryview 等二进制序列的独特特性
• 全部 Unicode 和陈旧字符集的编解码器
• 避免和处理编码错误
• 处理文本文件的最佳实践
• 默认编码的陷阱和标准 I/O 的问题
• 规范化 Unicode 文本,进行安全的比较
• 规范化、大小写折叠和暴力移除音调符号的实用函数
• 使用 locale 模块和 PyUCA 库正确地排序 Unicode 文本
• Unicode 数据库中的字符元数据
• 能处理字符串和字节序列的双模式 API

4.1 4.2 4.3 字符问题、字节概要 基本的编解码器

主要讲了
python2、python3 的str、unicode、bytes之间的差异
编码解码的概念
memoryview、struct模块对字节序列的处理
对这一块不太感冒,只做一个python3的str、unicode、bytes的笔记

python3 的str其实就是unicode字符,交互界面看到的是人类的字符,但其实存储中是unicode码位(code point 四位十六进制的数)。
unicode其实就是做了一个人类所有字符码位的一个一一映射关系表
数据的传输永远都是二进制的,我们要传输unicode字符,就需要把码位转换成二进制数据,这就另外规定了很多不同的编码方式--utf-8 utf-16 GBK IOS-2312等,有的编码方式支持所有unicode码位到二进制的转换,比如utf系列,但有的只支持部门unicode码位,比如GBK!
python用bytes跟bytearray来表示二进制的字节,每个元素是介于0-255(2^8)之间的整数,即每个元素代表一个字节(8bits)

str.encode(encoding='')用于把str编码成bytes类型
bytes.decode(encoding='')用于把bytes类型解码成str类型

4.4了解编解码问题

编解码相关的异常种类为UnicodeEncodeError和UnicodeDecodeError

处理UnicodeEncodeError

有的编码方式只能把部分unicode字符转换成字节序列,如果目标编码中没有定义某个字符,就会跑出UnicodeEncodeError异常
str.encode()函数里的errors参数规定了出现编码错误后程序的处理方式,默认为strict,直接抛UnicodeencodeError,但还有其他方式如ignore、replace、xmlcharrefreplace等
在这里插入图片描述

处理UnicodeDecodeError

并非所有字节序列都能转换成unicode字符,如果转换失败,就会抛UnicodeDecodeError,bytes.decode()函数同样有errors参数,参数类型跟str.encode的相同。
有的旧编码比如’cp1252’ ‘iso8859_1’ 'koi8_r’能够解码任何字节序列而不抛出错误,但会得到错误的字符

在这里插入图片描述

判断字节序列的编码

如果只拿到字节序列,我们不能百分百猜出它是用什么编码格式编码的,是utf-8还是gbk,不清楚
往往通信的时候需要规定跟说明编码格式,比如http跟xml都需要在头部说明编码方式
如果没有给定编码方式,就只能靠猜测了,Chardet模块就是用来做编码格式猜测的

BOM用于判断大端还是小端

用utf-16把字符写入文本时,往往会在开头写入额外的两个字节,这两个字节就是BOM,如果是FFFE 那么就是小端,如果是FEFF,那么就是大端,下面的例子中是FFFE,打印b[2]=97是’a’字符的低字节序,b[3]=0是’a’字符的高字节序,说明使用小端模式

>>> a='abc'
>>> b=a.encode('utf-16')
>>> b
b'\xff\xfea\x00b\x00c\x00'
>>> b[0]
255
>>> b[1]
254
>>> b[2]
97
>>> b[3]
0

UTF-16有两个变种:UTF-16LE UTF-16BE 显式指定小端模式和显式指定大端模式,使用者两个变种不会产生BOM

4.5 处理文本文件

两句话,输入输出时把字节序列解码成unicode,处理过程中全程用unicode。
输入输出指定编码方式,不要使用默认编码,特别是window系统。

4.6规范化Unicode字符串

Unicode有组合字符–变音符号和附加到前一个字符上的记号,打印时作为一个整体
在这里插入图片描述

正常来说s1 s2虽然码位不同,但表示出来是一样的,程序应该判定两者一致的,但python不会,为了避免这种问题,要用unicodedata.normalize 函数提供的 Unicode 规范化,函数的第一个参数是下面四个之一[“NFC”,“NFD”,“NFKC”,“NFKD”]
NFC(Normalization Form C)使用最少的码位构成等价的字符串
NFD 把组合字符分解成基字符和单独的组合字符
在这里插入图片描述

使用NFC时,有的单字符会被转换成另一个单字符,这类字符是视觉上相同但符号位不同的字符

NFKC、NFKD在NFC、NFD的基础上再考虑一些兼容字符

在这里插入图片描述
使用 NFKC 和 NFKD 规范化形式时要小心,而且只能在特殊情况中使用,例
如搜索和索引,而不能用于持久存储,因为这两种转换会导致数据损失

4.6.1 大小写折叠

把unicode文本变成小写,标准函数是str.casefold() str.lower()功能类似,但有少数例外,两者对unicode处理结果不同的有116个码位

可以根据项目要求做unicode字符的自定义规范化,比如去掉变音符号,把一些拉丁文字符映射成英文等

4.7 Unicode文本排序

4.8 Unicode数据库

unicodedata库不仅包括码位与字符名称之间的映射,还有各个字符的元数据,以及字符之间的关系。例如,unicodedata记录了字符是否可以打印、是不是字母、是不是数字,或者是不是其他数值符号。字符串的 isidentifier、isprintable、isdecimal 和 isnumeric 等方法就是靠这些信息作判断的

4.9 支持字符串和字节序列的双模式API

标准库中有的函数支持接收字符串或者字节序列作为参数,比如re os中的一些函数

  • re库
    在这里插入图片描述

  • os库
    os模块所有函数中文件名或路径名参数都可以是字符串或者字节序列
    在这里插入图片描述
    为了方便手动处理字符串或者字节序列的文件名或者路径名,os提供特殊的编解码函数
    fsencode(filename)不管filename是字符串还是字节序列,最终返回字节序列
    fsdecode(filename)不管filename是字符串还是字节序列,最终返回字符串
    unix平台上这两个函数用surrogateescape错误处理方式,避免遇到意外字节序列时卡住,window用strict
    surrogateescape把无法理解的字节序列替换成Unicode 中 U+DC00 到 U+DCFF 之
    间的码位(Unicode 标准把这些码位称为“Low Surrogate Area”),这些码位是保留的,
    没有分配字符,供应用程序内部使用。编码时,这些码位会转换成被替换的字节值
    在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值