字符/文本编码解码笔记

  • 1.字符问题
    • 编码和解码
  • 2.字节概要
  • 3.基本的编解码器
    • 编码类型史
      • 字符编码
      • ASCII码
      • GB2312以及其他编码
      • UNICODE标准编码
      • UTF-8编码
  • 4.了解编解码问题
    • 处理UnicodeEncoderError
      • 解决方法:
    • 处理UnicodeDecodeError
      • 解决方法
  • 5.修改源代码编码
  • 6.查看文件编码方式
    • 终端查看文件编码方式
    • 代码内查看文件编码方式
  • 7.处理文本文件
    • 查看open函数默认编码方式

1.字符问题

“字符串”是个相当简单的概念:一个字符串是一个字符序列。
在 2015 年,“字符”的最佳定义是 Unicode 字符。因此,从 Python 3 的 str 对象中获取的元素是 Unicode 字符。但是Python 3 默认使用 UTF-8 编码源码。注意区分。
Unicode 标准把字符的标识和具体的字节表述进行了如下的明确区分。

  • 字符的标识,即码位,是 0~1 114 111 的数字(十进制),在 Unicode 标准中以 4~6 个十六进制数字表示,而且加前缀“U+”。例如,字母 A 的码位是 U+0041。
  • 字符的具体表述取决于所用的编码,也就是除了Unicode以外其他编码的表示。编码是在码位和字节序列之间转换时使用的算法。比如在 UTF-8 编码中,A(U+0041)的码位编码成单个字节 \x41。一个字符串则编码为由多个字节组成的字节序列。后面会多处提到字节序列,把它当成用其他编码器对Unicode字符编码的结果就可以了。

编码和解码

编码是把码位转换成字节序列的过程。通俗的讲就是将Unicode编码的字符转化为其他编码的字符。
解码是把字节序列转换成码位的过程。通俗的讲就是将其他编码的字符转化为Unicode编码的字符。

s='sabér'
print(s)
print(len(s)) #1
b=s.encode('utf-8') #2
print(b) #3
print(len(b)) #4
x=b.decode('utf-8')#5
print(x)

输出:

sabér
5
b'sab\xc3\xa9r'
6
sabér
  • 1.'sabér'字符串有5个Unicode字符。
  • 2.使用UTF-8把str对象编码成bytes对象。
  • 3.bytes字面量以b开头,表示字节序列。
  • 4.字节序列 b 有 5 个字节(在 UTF-8 中,“é”的码位编码成两个字节)。
  • 5.使用 UTF-8 把 bytes 对象(字节对象)解码成str 对象。

由于Unicode编码是标准编码格式,也可以看做是没有任何特定编码格式的“无编码”模式。所以,对于任何Unicode类型编码的字符,打印时python会自动根据环境编码转为特定编码后再显示,Python 3 为所有平台设置的默认编码都是 UTF-8。

2.字节概要

Python 内置了两种基本的二进制序列类型:不可变 bytes 类型和 可变 bytearray 类型。

3.基本的编解码器

Python 自带了超过 100 种编解码器(codec, encoder/decoder),用于在文本和字节之间相 互转换。每个编解码器都有一个名称,如 ‘utf_8’,而且经常有几个别名,如 ‘utf8’、‘utf-8’ 和 ‘U8’。

  • 上图有12个字符,code point表示其码位,还有7种编码的字节表述(十六进制)。
  • 星号表明,某些编码(如 ASCII 和多字节的 GB2312)不能表示所有 Unicode 字符。然而,UTF 编码的设计目的就是处理每一个 Unicode 码位。

编码类型史

字符编码

将人类语言转化为计算机能够理解的二进制的数(0,1),我们用bit(位)来表示,通常转化的时候是按byte(字节)来处理,一个字节等于8bit。

ASCII码

ASCII码是人类计算机历史上最早发明的字符集,ASCII码是专门为表示英文、数字以及英文标点符号而生。ASCII编码使用一个字节编码,一个字节有256种组合,足够存储这些字符。

GB2312以及其他编码

由于中文汉字非常多,ASCII无法满足汉字存储的需求。
为了满足国内在计算机中使用汉字的需要,中国国家标准总局发布了一系列的汉字字符集国家标准编码,统称为GB码,或国标码
其中最有影响的是于1980年发布的《信息交换用汉字编码字符集 基本集》,标准号为GB 2312-1980,因其使用非常普遍,也常被通称为国标码。GB2312编码通行于我国内地;新加坡等地也采用此编码。几乎所有的中文系统和国际化的软件都支持GB 2312。
所以,大家可以理解为,GB系列的编码是为了适应复杂的中文编码而对ASCII码的一种扩充。

UNICODE标准编码

每个国家都会对ASCII码扩展出自己的一套编码,就存在不同编码之间的转换和显示问题。为了解决这个问题,需要一套统一的编码格式,即Unicode。
Unicode又被称为统一码、万国码;它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。
Unicode编码通常由两个字节组成,共表示256*256个字符,即所谓的UCS-2。某些偏僻字还会用到四个字节,即所谓的UCS-4。
并且Unicode兼容ASCII,在Unicode中,原本ASCII中的127个字符只需在前面补一个全零的字节即可。

UTF-8编码

UNICODE编码有个缺点,所有语言的字符都是固定长度的存储,有些语言的字符只需占用少量的存储空间,这就导致浪费了大量的存储空间。
为了解决这个问题,就出现了一些中间格式的字符集,他们被称为通用转换格式,即UTF(Unicode Transformation Format)。
我们最常用的UTF-8就是这些转换格式中的一种。UTF-8编码其实是一种可“变长”的编码格式,即把英文变长为1个字节,而汉字用3个字节表示,特别生僻的还会变成4-6字节。

该部分参考:一文搞懂Python字符编码问题

4.了解编解码问题

虽然有个一般性的 UnicodeError 异常,但是报告错误时几乎都会指明具体的异常:UnicodeEncodeError(把字符串转换成二进制序列时)或 UnicodeDecodeError(把二进制序列转换成字符串时)。如果源码的编码与预期不符, 加载 Python 模块时还可能抛出 SyntaxError。

处理UnicodeEncoderError

多数非 UTF 编解码器只能处理 Unicode 字符的一小部分子集。把文本(Unicode 字符)转换成字节序列时,如果目标编码中没有定义某个字符,那就会抛出 UnicodeEncodeError 异常。

解决方法:

  • 1.在encode()函数中添加参数error,举例如下:
city = 'São Paulo'
x=city.encode('cp437', errors='ignore')
print(x)
y=city.encode('cp437', errors='replace')
print(y)
z=city.encode('cp437', errors='xmlcharrefreplace')
print(z)

输出:

b'So Paulo'
b'S?o Paulo'
b'São Paulo'

error=‘ignore’ 处理方式悄无声息地跳过无法编码的字符;
error='replace’把无法编码的字符替换成 ‘?’;
error=‘xmlcharrefreplace’ 把无法编码的字符替换成 XML实体。

以上解决是十分不妥的,损坏了数据。
编解码器的错误处理方式是可扩展的。你可以为 errors 参数注册额外的字符串,方法是把一个名称和一个错误处理函数传给 codecs.register_error 函数。 参见 codecs.register_error 函数的官方文档。

  • 2.换一种编码器,尽量使用UTF-8编码器。

处理UnicodeDecodeError

ASCII字符有127个,但是一个字节表示的空间有256个。所以不是每一个字节都包含有效的 ASCII 字符。
同理,不是每一个字符序列都是有效的 UTF-8 或 UTF-16。
把二进制序列(字节序列)转换成文本(Unicode字符)时,如果字节序列有无效的字节时,遇到无法转换的字节序列时会抛出 UnicodeDecodeError。
举例如下:

octets = b'Montr\xe9al'
oct=octets.decode('cp1252')
print(oct)
oct1=octets.decode('utf_8')
print(oct1)
oct2=octets.decode('utf_8', errors='replace')
print(oct2)

输出:

Montréal
Traceback (most recent call last):File "c:\Users\13451\Desktop\python基本操作\1.py", line 18, in <module>oct1=octets.decode('utf_8')
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe9 in position 5: invalid continuation byte
'Montral'
  • 这些字节序列是使用 latin1 编码的“Montréal”;’\xe9’ 字节对应“é”。
  • 可以使用 ‘cp1252’(Windows 1252)解码,因为它是 latin1 的有效超集。
  • ‘utf_8’ 编解码器检测到 octets 不是有效的 UTF-8 字符串,抛出 UnicodeDecodeError。bug中position从零开始数。

解决方法

使用 ‘replace’ 错误处理方式,\xe9 替换成了替换字符(码位是 U+FFFD),这是官方指定的 REPLACEMENT CHARACTER(替换字符),表示未知字符。替换字符:形状为黑色菱形,且中间填充了一个问号。

5.修改源代码编码

Python 3 默认使用 UTF-8 编码源码且Python 3 为所有平台设置的默认编码都是 UTF-8。
在源代码第一行加# coding: cp1252即可用cp1252编码,或者编辑器或IDE都有更改编码的途径。

6.查看文件编码方式

终端查看文件编码方式

安装统一字符编码侦测包 Chardet。
终端使用:

chardetect 1.py

输出:

1.py: utf-8 with confidence 0.99

表示1.py有0.99的可能是utf-8编码。

代码内查看文件编码方式

使用chardet库的detect函数

import chardet
file1='data/test.txt'
f=open(file1,'rb')
f_encoding=chardet.detect(f.read())
print(f_encoding)
f.close()

输出:

{'encoding': 'utf-8', 'confidence': 0.99, 'language': ''}

7.处理文本文件

使用open()函数打开文件,有两种方式处理文件:文本模式二进制模式
添加encoding参数可以设置编码方式,这个编码方式在编码输出文本的时候会用到,即下图第三行。open()函数默认采用文本模式。默认编码方式取决于平台,window10下为gbk,linux下为utf-8。当处于二进制模式时不能添加encoding参数,因为本身就是二进制了,不需要再编码。

  • 如果调用read()函数,open 函数会在读取文件时做必要的解码(自动解码成Unicode字符,即str)。对应下图解码输入的字节序列,得到str对象。
  • 如果调用write()函数,以文本模式写入文件时还会做必要的编码。参数为str对象。对应下图第三行,生成字节序列(bytes)。

整个处理文本文件的过程如下图:

查看open函数默认编码方式

file1='data/test.txt'
fp=open(file1,'w')
print(fp)
fp.close()

win10下输出:

<_io.TextIOWrapper name='data/test.txt' mode='w' encoding='cp936'>

cp936即 code page 936(代码页936)是以GBK(国标扩展字符集)为基础的编码。基本和GBK差不多。

关于编码默认值的最佳建议是:别依赖默认值。如果遵从 Unicode 三明治的建议,而且始终在程序中显式指定编码,那将避免很多问题。

参考了流畅的python第四章。

python--字符/文本编码解码笔记相关推荐

  1. python使用base64编码解码数据

    python使用base64编码解码数据 base64模块是用来作base64编码解码,常用于小型数据的传输.编码后的数据是一个字符串,其包括a-z.A-Z.0-9./.+共64个字符,即可用6个字节 ...

  2. 利用Huffman树进行文本编码解码的实现

    --------------------------------- 功能:利用Huffman树进行文本编码解码的实现 环境:WinXP,VC6.0 输入:C:\\in.txt 输出:C:\\out.d ...

  3. JavaScript 文本编码解码详解笔记

    JavaScript 文本的编码解码 文本编码 文本编码方法分为批量编码和流编码. 1.批量编码 所谓批量编码,指的是JavaScript引擎会同步编码整个字符串.对于非常长的字符串,可能会花较长时间 ...

  4. 29 Python - 字符与编码

    字符与编码 01 字符串本质 Python字符串相关概念 字符串     str 字节       bytes 字节数组   bytearray 电脑字符串存储机制 字符库:A.B每个字符有一个代码点 ...

  5. python 字符的编码和解码

    什么是编码 编码是信息从一种形式或格式转换为另一种形式的过程.例如,将字符A使用ascll编码,首先在ascll中找到字符A对应的一个数字,再将该数字转化为二进制形式,供计算机读取.而不同的编码方式中 ...

  6. python基础(十二):字符字节编码解码

    基础(十二) 字符串概述 类型 编码架构 字符串存储 常用字符编码 ASCII latin-1 UTF-8(通用性更好) UTF-16 UTF-32 内置函数 ord() chr() str.enco ...

  7. python 字符的编码

    参考 廖雪峰-字符串和编码 https://blog.csdn.net/weixin_41789688/article/details/116787795 Unicode编码详解(一):Unicode ...

  8. 使用python对url编码解码

    最近在抓取一些js代码产生的动态数据,需要模拟js请求获得所需用的数据,遇到对url进行编码和解码的问题,就把遇到的问题总结一下,有总结才有进步,才能使学到的知识更加清晰.对url进行编码和解码,py ...

  9. 使用python对url编码解码 (转)

    写cgi经常碰到的一个问题就是对url进行编码和解码,python提供了很方便的接口进行调用. url中的query带有特殊字符(不是url的保留字)时需要进行编码. 当url中带有汉字时,需要特殊的 ...

最新文章

  1. Ie html button消失,input 按钮在IE下兼容问题
  2. 【CV】基于python和OpenCV构建智能停车系统
  3. php 新浪url,PHP URL函数详解
  4. 找回Kitkat的AppOps
  5. 捍卫军人的尊严(武汉548公交车一幕)
  6. Java 异步回调机制实例解析
  7. 对短链接服务暴露的URL进行网络侦察
  8. 2018年下半年系统集成项目管理工程师真题及答案解析
  9. 瑞利分布与瑞利衰落信道
  10. h3c 出口路由器mac地址过滤
  11. 手把手教你用Python网络爬虫获取壁纸图片!
  12. Canal.deployer 启动报错说CHARACTER SET 'utf8' COLLATE 'utf8_unico', expect null,rkdown编辑器
  13. 两款程序员的好帮手——BitNami,Hoo WinTail
  14. 数据库课程设计------书店管理系统
  15. ipynb文件过大打开浏览器崩溃解决方法
  16. column ‘_id‘ does not exis报错
  17. 2018年天津大学夏令营机试第一题
  18. c语言300行代码大作业,C语言300行代码
  19. 【oracle】oracle创建表、创建索引、创建自增id
  20. Libevent之信号事件管理

热门文章

  1. couchbase_具有Couchbase,Java EE和WildFly的CRUD Java应用程序
  2. neo4j cypher_Neo4j:使用Cypher生成实时建议
  3. 摆脱冷气_摆脱匿名类
  4. Apache Camel 3.2 – Camel的无反射配置
  5. 只读副本和Spring Data第4部分:配置只读存储库
  6. 使用Spring Cloud HystrixCommands的功能Hystrix
  7. 提示:通过URL激活并发送参数
  8. junit测试方法_JUnit测试方法订购
  9. 为什么猫王不应该访问Java
  10. ANTLR和Jetbrains MPS:解析文件并以树符号显示AST