python之字符串的编码问题

你好, 我是木木, 目前正在做两件事
  1. 沉淀自己的专业知识
  2. 探索了解各种副业项目,同时将探索过程进行分享,帮助自己以及更多朋友找到副业, 做好副业

字符串的编码问题

我们都知道计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字才能处理。
字符串的编码问题主要涉及到字符集和编码方式。
字符集是一组字符的集合,用于表示各种文字和符号。常见的字符集有ASCII、Unicode等
编码方式是将字符集中的字符转换为计算机可以识别的数字或二进制序列的过程。常见的编码方式有UTF-8、GBK等
因为 Python 的诞生比 Unicode 标准发布的时间还要早,所以最早的Python 只支持 ASCII 编码,普通的字符串 ‘ABC’ 在 Python 内部都是 ASCII 编码的。
Python 在后来添加了对 Unicode 的支持,以 Unicode 表示的字符串用u'...'表示。
不过在最新的 Python 3 版本中,字符串默认是 Unicode 编码的,当然, Python3是支持多语言的。就像上面的例子一样,我的代码中没有加u'...',也能正常显示。
不过由于 Python 源代码也是一个文本文件,所以,当你的源代码中包含中文的时候,在保存源代码时,就需要务必指定保存为 UTF-8 编码。当Python 解释器读取源代码时,为了让它按 UTF-8 编码读取,我们通常在文件开头写上这两行:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

第一行注释是为了告诉 Linux/OS X 系统,这是一个 Python 可执行程序,Windows 系统会忽略这个注释;
第二行注释是为了告诉 Python 解释器,按照 UTF-8 编码读取源代码,否则,你在源代码中写的中文输出可能会有乱码。
申明了 UTF-8 编码意味着你的 .py 文件就是 UTF-8 编码的,必须并且要确保文本编辑器正在使用 UTF-8 without BOM 编码
当你需要将字符串存储到文件或通过网络传输时,需要将其编码为其他字符集,如UTF-同样地,在读取文件或接收网络数据时,需要将数据解码为Unicode字符串
例如,将一个Unicode字符串编码为UTF-8格式:

unicode_str = "你好,世界!"
utf8_encoded = unicode_str.encode("utf-8")
print(utf8_encoded)

将一个UTF-8编码的数据解码为Unicode字符串:

utf8_data = b'\xe4\xbd\xa0\xe5\xa5\xbd\xef\xbc\x8c\xe4\xb8\x96\xe7\x95\x8c\xef\xbc\x81'
decoded_str = utf8_data.decode("utf-8")
print(decoded_str)

unicode和utf8有什么区别(进阶)

Unicode为每个字符提供一个唯一的码点,而UTF-8是将这些码点转换为字节序列的规则, 或者说Unicode是分配给一系列字符的一系列数字,而UTF-8,是把这一系列数字存储成计算机文件的其中一种实现方案
Unicode是一种为字符分配编号的方案,一个字符的Unicode编号(又称为码点)是一个数字
比如,“虎”字的Unicode码点为“864E”,通常写作“U+864E”,也就是十进制的34382
Unicode是数与字符的对应关系,它是一种概念,所以它只对人类有意义。
计算机不能处理和存储概念,只能处理和存储数据。所以我们必须想个办法,把Unicode的概念转换成计算机可以处理的具体数据,而这就是“UTF”(Unicode Transformation Format,Unicode转换格式,Unicode转写方式)
“UTF”的设计目的,是把Unicode规范为字符分配的编号转换为计算机可以直接存储和处理的“八位字节序列”
Unicode码点是一个数,它的取值范围是十六进制的0到10FFFF,如果要转换为8位字节,就需要1字节到3字节的存储空间,不同的码点需要的字节数不同
但是,如果直接按码点所需的最小字节数进行存储,在读取时就会产生问题:我们怎么知道一个码点有多少字节
拿“虎”(U+864E)及其emoji图案(U+1F405)举例,存储它俩最少只要5字节,十六进制表示为“86 4E 01 F4 05”。
但是如果真的这样存储,读取时就会陷入困境,因为字节和字节之间是没有边界的,我们不知道“86 4E 01 F4 05”中的哪部分属于第一个字符,哪部分属于第二个字符。我们甚至不知道“86 4E 01 F4 05”到底表示了几个字符,因为这一串序列可以拆分成多种形式
不同的拆分方法将得到完全不同的字符,所以这种存储方式肯定是不可行的
首先想到的方案就是固定长度。既然拆分难是因为不同码点的字节数不同,那把字节数少的前面补0填充到和字节数多的一样长不就可以了吗?
UTF-24: 既然Unicode的最大码点占3字节,那就所有码点都补0到3字节后再存储
该方案最大的问题在于它是3字节为一组,但计算机一次只能读取1、2、4、8个字节。所以计算机要么分两次读取,先读取2字节再读取1字节,要么一次性读取4字节再删除1字节,操作都不是很方便
UTF-32: 既然计算机一次只能读取1、2、4、8个字节,那干脆用4个字节存储一个码点。这样“U+864E、U+1F405”就存储为“00 00 86 4E 00 01 F4 05”,浪费一个字节就浪费嘛,反正现在的设备内存硬盘都很大
缺点, 显而易见,占用空间大,存储一个字符最少浪费1字节,最多浪费3字节!虽然现代计算机内存和硬盘都很大,但是网速却往往不够快,有的还是按流量计费的。如果要通过网络发送文本,采用UTF-32似乎不太经济
UTF-16:用2-4个自己表示,
UTF-8:用1-4个自己表示实现了可变字节数的字符编码
UTF-16和UTF-8都是通过在字节内部把边界表示出来的
比如:
如果第一个字节是0xxxxxxx,表示该字符只有1字节。
如果第一个字节是110xxxxx,表示该字符有2字节。
如果第一个字节是1110xxxx,表示该字符有3字节。
如果第一个字节是11110xxx,表示该字符有4字节


好了,本章节到此告一段落了,希望对你有所帮助

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值