一文读懂字符编码从此解决乱码问题

2024-03-15 13:30

本文主要是介绍一文读懂字符编码从此解决乱码问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 一、 引入
  • 二、 知识储备
    • 2.1 三大核心硬件
    • 2.2 文本编辑器读取文件内容的流程
    • 2.3 python解释器执行文件的流程
    • 2.4 总结
  • 三、字符编码介绍
    • 3.1 什么是字符编码?
    • 3.2 字符编码表的发展史 (了解)
      • 3.2.1 阶段一:一家独大阶段
      • 3.2.2 阶段二:诸侯割据、天下大乱
      • 3.2.3 阶段三:分久必合
    • 3.3 编码与解码
    • 3.4 utf-8的由来
  • 四、 字符编码的应用
    • 4.1 文本编辑器nodpad++存取文本文件
      • 1. 存乱了
      • 2. 取乱了
    • 4.2 python解释器执行文件的前两个阶段
    • 4.3 python解释器执行文件的第三个阶段

一、 引入


​ 字符串类型、文本文件的内容都是由字符组成的,但凡涉及到字符的存取,都需要考虑字符编码的问题。
​ 字符编码这个知识点的典型特征就是理论多、结论少,但对于开发而言只需要记住结论即可。


二、 知识储备

2.1 三大核心硬件

所有软件都是运行硬件之上的,与运行软件相关的三大核心硬件为cpu、内存、硬盘,我们需要明确三点

  1. 软件运行前,软件的代码及其相关数据都是存放于硬盘中的

  2. 任何软件的启动都是将数据从硬盘中读入内存,然后cpu从内存中取出指令并执行

  3. 软件运行过程中产生的数据最先都是存放于内存中的,若想永久保存软件产生的数据,则需要将数据由内存写入硬盘

在这里插入图片描述

2.2 文本编辑器读取文件内容的流程

  • 阶段1、启动一个文件编辑器(文本编辑器如nodepad++,pycharm,word)
  • 阶段2、文件编辑器会将文件内容从硬盘读入内存
  • 阶段3、文本编辑器会将刚刚读入内存中的内容显示到屏幕上

2.3 python解释器执行文件的流程

以python test.py为例,执行流程如下

  • 阶段1、启动python解释器,此时就相当于启动了一个文本编辑器
  • 阶段2、python解释器相当于文本编辑器,从硬盘上将test.py的内容读入到内存中
  • 阶段3、python解释器解释执行刚刚读入的内存的内容,开始识别python语法

2.4 总结

python解释器与文本编辑的异同如下

  1. 相同点:前两个阶段二者完全一致,都是将硬盘中文件的内容读入内存,详解如下
    python解释器是解释执行文件内容的,因而python解释器具备读py文件的功能,这一点与文本编辑器一样

  2. 不同点:在阶段3时,针对内存中读入的内容处理方式不同,详解如下
    文本编辑器将文件内容读入内存后,是为了显示或者编辑,根本不去理会python的语法,而python解释器将文件
    内容读入内存后,是为了执行python代码、会识别python语法)


三、字符编码介绍

3.1 什么是字符编码?

人类在与计算机交互时,用的都是人类能读懂的字符,如中文字符、英文字符、日文字符等,而计算机只能识别二进制数,详解如下:

二进制数即由0和1组成的数字,例如010010101010。计算机是基于电工作的,电的特性即高低电平,人类从逻辑层面将高电平对应为数字1,低电平对应为数字0,这直接决定了计算机可以识别的是由0和1组成的数字毫无疑问,由人类的字符到计算机中的数字,必须经历一个过程,如下
在这里插入图片描述
翻译的过程必须参照一个特定的标准,该标准称之为字符编码表,该表上存放的就是字符与数字一一对应的关系。
字符编码中的编码指的是翻译或者转换的意思,即将人能理解的字符翻译成计算机能识别的数字

3.2 字符编码表的发展史 (了解)

字符编码的发展经历了三个重要的阶段,如下

3.2.1 阶段一:一家独大阶段

现代计算机起源于美国,所以最先考虑仅仅是让计算机识别英文字符,于是诞生了ASCII表
在这里插入图片描述

ASCII表的特点:
1、只有英文字符与数字的一一对应关系
2、一个英文字符对应1Bytes,1Bytes=8bit,8bit最多包含256个数字,可以对应256个字符,足够表示所有英文字符

3.2.2 阶段二:诸侯割据、天下大乱

为了让计算机能够识别中文和英文,中国人定制了GBK

# GBK表的特点:
1、只有中文字符、英文字符与数字的一一对应关系
2、一个英文字符对应1Bytes一个中文字符对应2Bytes   补充说明:1Bytes=8bit,8bit最多包含256个数字,可以对应256个字符,足够表示所有英文字符2Bytes=16bit,16bit最多包含65536个数字,可以对应65536个字符,足够表示所有中文字符

每个国家都各自的字符,为让计算机能够识别自己国家的字符外加英文字符,各个国家都制定了自己的字符编码表

# Shift_JIS表的特点:1、只有日文字符、英文字符与数字的一一对应关系# Euc-kr表的特点:1、只有韩文字符、英文字符与数字的一一对应关系

此时,美国人用的计算机里使用字符编码标准是ASCII、中国人用的计算机里使用字符编码标准是GBK、日本人用的计算机里使用字符编码标准是Shift_JIS,如下图所示,
在这里插入图片描述

字符编码发展到了这个阶段,可以用一句话概括:诸侯割据、天下大乱,详解如下
图1中,文本编辑存取文件的原理如下:

文本文件内容全都为字符,无论存取都是涉及到字符编码问题
#1、存文本文件
人类通过文本编辑器输入的字符会被转化成ASCII格式的二进制存放于内存中,如果需要永久保存,
则直接将内存中的ASCII格式的二进制写入硬盘
#2、读文本文件
直接将硬盘中的ASCII格式的二进制读入内存,然后通过ASCII表反解成英文字符

图2图3都是相同的过程,此时无论是存还是取由于采用的字符编码表一样,所以肯定不会出现乱码问题,但问题是在美国人用的计算机里只能输入英文字符,而在中国人用的计算机里只能输入中文字符和英文字符…,毫无疑问我们希望计算机允许我们输入万国字符均可识别、不乱码,而现阶段计算机采用的字符编码ASCII、GBK、Shift_JIS都无法识别万国字符,所以我们必须定制一个兼容万国字符的编码表,请看阶段三

3.2.3 阶段三:分久必合

在这里插入图片描述

unicode于1990年开始研发,1994年正式公布,具备两大特点:

  1. 存在所有语言中的所有字符与数字的一一对应关系,即兼容万国字符

  2. 与传统的字符编码的二进制数都有对应关系,详解如下:

很多地方或老的系统、应用软件仍会采用各种各样传统的编码,这是历史遗留问题。此处需要强调:软件是存放于硬盘的,而运行软件是要将软件加载到内存的,面对硬盘中存放的各种传统编码的软件,想让我们的计算机能够将它们全都正常运行而不出现乱码,内存中必须有一种兼容万国的编码,并且该编码需要与其他编码有相对应的映射/转换关系,这就是unicode的第二大特点产生的缘由
在这里插入图片描述

文本编辑器输入任何字符都是最新存在于内存中,是unicode编码的,存放于硬盘中,则可以转换成任意其他编码,只要该编码可以支持相应的字符

# 英文字符可以被ASCII识别
英文字符--->unciode格式的数字--->ASCII格式的数字# 中文字符、英文字符可以被GBK识别
中文字符、英文字符--->unicode格式的数字--->gbk格式的数字# 日文字符、英文字符可以被shift-JIS识别
日文字符、英文字符--->unicode格式的数字--->shift-JIS格式的数字

3.3 编码与解码

由字符转换成内存中的unicode,以及由unicode转换成其他编码的过程,都称为编码encode
在这里插入图片描述

由内存中的unicode转换成字符,以及由其他编码转换成unicode的过程,都称为解码decode
在这里插入图片描述

在诸多文件类型中,只有文本文件的内存是由字符组成的,因而文本文件的存取也涉及到字符编码的问题

3.4 utf-8的由来

注意:如果保存到硬盘的是GBK格式二进制,当初用户输入的字符只能是中文或英文,同理如果保存到硬盘的是Shift_JIS格式二进制,当初用户输入的字符只能是日文或英文……如果我们输入的字符中包含多国字符,那么该如何处理?

#多国字符—√—》内存(unicode格式的二进制)——X—》硬盘(GBK格式的二进制)#多国字符—√—》内存(unicode格式的二进制)——X—》硬盘(Shift_JIS格式的二进制)#多国字符—√—》内存(unicode格式的二进制)——√—》硬盘(???格式的二进制)

理论上是可以将内存中unicode格式的二进制直接存放于硬盘中的,但由于unicode固定使用两个字节来存储一个字符,如果多国字符中包含大量的英文字符时,使用unicode格式存放会额外占用一倍空间(英文字符其实只需要用一个字节存放即可),然而空间占用并不是最致命的问题,最致命地是当我们由内存写入硬盘时会额外耗费一倍的时间,所以将内存中的unicode二进制写入硬盘或者基于网络传输时必须将其转换成一种精简的格式,这种格式即utf-8(全称Unicode Transformation Format,即unicode的转换格式)

# 多国字符——》内存(unicode格式的二进制)———》硬盘(utf-8格式的二进制)

在这里插入图片描述

那为何在内存中不直接使用utf-8呢?
utf-8是针对Unicode的可变长度字符编码:一个英文字符占1Bytes,一个中文字符占3Bytes,生僻字用更多的Bytes存储
unicode更像是一个过渡版本,我们新开发的软件或文件存入硬盘都采用utf-8格式,等过去几十年,所有老编码的文件都淘汰掉之后,会出现一个令人开心的场景,即硬盘里放的都是utf-8格式,此时unicode便可以退出历史舞台,内存里也改用utf-8,天下重新归于统一


四、 字符编码的应用

我们学习字符编码就是为了存取字符时不发生乱码问题:

1、内存中固定使用unicode无论输入任何字符都不会发生乱码2、我们能够修改的是存/取硬盘的编码方式,如果编码设置不正确将会出现乱码问题。
乱码问题分为两种:存乱了,读乱了2.1 存乱了:如果用户输入的内容中包含中文和日文字符,如果单纯以shift_JIS存,
日文可以正常写入硬盘,而由于中文字符在shift_jis中没有找到对应关系而导致存乱了2.2 读乱了:如果硬盘中的数据是shift_JIS格式存储的,采GBK格式读入内存就读乱了

总结:

  1. 保证存的时候不乱:在由内存写入硬盘时,必须将编码格式设置为支持所输入字符的编码格式
  2. 保证取的时候不乱:在由硬盘读入内存时,必须采用与写入硬盘时相同的编码格式

4.1 文本编辑器nodpad++存取文本文件

文本编辑器存取的都是文本文件,而文本文件中包含的内容全为字符,所以存取文本文件都涉及到字符编码的问题。

1. 存乱了

在这里插入图片描述

文本中既有中文也有韩文,如果用韩文编码方式保存文件时候,如果再次打开文件,中文是肯定会乱码的,这叫存乱了。

在这里插入图片描述

2. 取乱了

现在,我们用gb2321格式保存一段中文
在这里插入图片描述
我们用ANSI格式打开,就会出现乱码,因为存与取的编码方式不一致
在这里插入图片描述
在以gb2312格式打开,又能恢复正常
在这里插入图片描述
存乱了对文文件是不可逆的,数据已经被破坏了,取乱了只要以相同的编码取就可解决乱码问题

4.2 python解释器执行文件的前两个阶段

执行py文件的前两个阶段就是python解释器读文本文件的过程,与文本编辑读文本文件的前两个阶段没人任何区别,要保证读不乱码,则必须将python解释器读文件时采用的编码方式设置为文件当初写入硬盘时的编码格式,如果没有设置,python解释器则才用默认的编码方式,在python3中默认为utf-8,在python2中默认为ASCII,我们可以通过指定文件头来修改默认的编码
在文件首行写入包含#号在内的以下内容

# coding: 当初文件写入硬盘时采用的编码格式

解释器会先用默认的编码方式读取文件的首行内容,由于首行是纯英文组成,而任何编码方式都可以识别英文字符。

4.3 python解释器执行文件的第三个阶段

设置文件头的作用是保证运行python程序的前两个阶段不乱码,经过前两个阶段后py文件的内容都会以unicode格式存放于内存中。
在经历第三个阶段时开始识别python语法,当遇到特定的语法name = ‘上’(代码本身也都全都是unicode格式存的)时,需要申请内存空间来存储字符串’上’,这就又涉及到应该以什么编码存储‘上’的问题了。
在Python3中,字符串类的值都是使用unicode格式来存储
由于Python2的盛行是早于unicode的,因此在Python2中是按照文件头指定的编码来存储字符串类型的值的(如果文件头中没有指定编码,那么解释器会按照它自己默认的编码方式来存储‘上’),所以,这就有可能导致乱码问题

# coding:utf-8
x = '上' # x的值为untf-8格式的二进制
print(x) # 打印操作是将x的值,即utf-8格式的二进制交给终端,当终端收到后发现并不是unicode(只有unicode才与字符有对应关系),
所以终端会执行操作:utf-8二进制---解码-->unicode格式的二进制,解码的过程终端会采用自己默认的编码,
而在pycharm的终端默认编码为utf-8、windows下的cmd终端的默认编码为gbk,所以该打印操作在pycharm中显示正常,
而在windows下的cmd中则乱码# 在windows下的cmd中运行效果如下
C:\Users\Administrator>python2 E:\aaa.py
涓

python2后推出了一种补救措施,就是在字符串类型前加u,则会将字符串类型强制存储unicode,这就与python3保持一致了,对于unicode格式无论丢给任何终端进行打印,都可以直接对应字符不会出现乱码问题

# coding:utf-8
x = u'上' # 即便文件头为utf-8,x的值依然存成unicode

4.4 字符串encode编码与decode解码的使用

# 1、unicode格式------编码encode-------->其它编码格式
>>> x='上' # 在python3在'上'被存成unicode
>>> res=x.encode('utf-8')
>>> res,type(res) # unicode编码成了utf-8格式,而编码的结果为bytes类型,可以当作直接当作二进制去使用
(b'\xe4\xb8\x8a', <class 'bytes'>)# 2、其它编码格式------解码decode-------->unicode格式
>>> res.decode('utf-8') 
'上'

4.5 总结

分析过程x="上"内存
上-------翻译-----0101010
上《----翻译《-----0101010字符编码表就是一张字符与数字对应关系的表a-00
b-01
c-10
d-11ASCII表:1、只支持英文字符串2、采用8位二进制数对应一个英文字符串GBK表:1、支持英文字符、中文字符2、采用8位(8bit=1Bytes)二进制数对应一个英文字符串采用16位(16bit=2Bytes)二进制数对应一个中文字符串unicode(内存中统一使用unicode):1、兼容万国字符与万国字符都有对应关系2、采用16位(16bit=2Bytes)二进制数对应一个中文字符串个别生僻会采用4Bytes、8Bytesunicode表:内存人类的字符---------unicode格式的数字----------|                     ||                     ||硬盘                    |||                     ||                     |GBK格式的二进制       Shift-JIS格式的二进制老的字符编码都可以转换成unicode,但是不能通过unicode互转utf-8:英文->1Bytes汉字->3Bytes结论:1、内存固定使用unicode,我们可以改变的是存入硬盘采用格式英文+汉字-》unicode-》gbk英文+日文-》unicode-》shift-jis万国字符》-unicode-》utf-82、文本文件存取乱码问题存乱了:解决方法是,编码格式应该设置成支持文件内字符串的格式取乱了:解决方法是,文件是以什么编码格式存如硬盘的,就应该以什么编码格式读入内存3、python解释器默认读文件的编码python3默认:utf-8python2默认:ASCII指定文件头修改默认的编码:在py文件的首行写:#coding:gbk4、保证运行python程序前两个阶段不乱码的核心法则:指定文件头# coding:文件当初存入硬盘时所采用的编码格式5、python3的str类型默认直接存成unicode格式,无论如何都不会乱码保证python2的str类型不乱码x=u'上'6、了解python2解释器有两种字符串类型:str、unicode# str类型x='上' # 字符串值会按照文件头指定的编码格式存入变量值的内存空间# unicode类型x=u'上' # 强制存成unicode

这篇关于一文读懂字符编码从此解决乱码问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/812136

相关文章

好题——hdu2522(小数问题:求1/n的第一个循环节)

好喜欢这题,第一次做小数问题,一开始真心没思路,然后参考了网上的一些资料。 知识点***********************************无限不循环小数即无理数,不能写作两整数之比*****************************(一开始没想到,小学没学好) 此题1/n肯定是一个有限循环小数,了解这些后就能做此题了。 按照除法的机制,用一个函数表示出来就可以了,代码如下

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

如何解决线上平台抽佣高 线下门店客流少的痛点!

目前,许多传统零售店铺正遭遇客源下降的难题。尽管广告推广能带来一定的客流,但其费用昂贵。鉴于此,众多零售商纷纷选择加入像美团、饿了么和抖音这样的大型在线平台,但这些平台的高佣金率导致了利润的大幅缩水。在这样的市场环境下,商家之间的合作网络逐渐成为一种有效的解决方案,通过资源和客户基础的共享,实现共同的利益增长。 以最近在上海兴起的一个跨行业合作平台为例,该平台融合了环保消费积分系统,在短

购买磨轮平衡机时应该注意什么问题和技巧

在购买磨轮平衡机时,您应该注意以下几个关键点: 平衡精度 平衡精度是衡量平衡机性能的核心指标,直接影响到不平衡量的检测与校准的准确性,从而决定磨轮的振动和噪声水平。高精度的平衡机能显著减少振动和噪声,提高磨削加工的精度。 转速范围 宽广的转速范围意味着平衡机能够处理更多种类的磨轮,适应不同的工作条件和规格要求。 振动监测能力 振动监测能力是评估平衡机性能的重要因素。通过传感器实时监

缓存雪崩问题

缓存雪崩是缓存中大量key失效后当高并发到来时导致大量请求到数据库,瞬间耗尽数据库资源,导致数据库无法使用。 解决方案: 1、使用锁进行控制 2、对同一类型信息的key设置不同的过期时间 3、缓存预热 1. 什么是缓存雪崩 缓存雪崩是指在短时间内,大量缓存数据同时失效,导致所有请求直接涌向数据库,瞬间增加数据库的负载压力,可能导致数据库性能下降甚至崩溃。这种情况往往发生在缓存中大量 k

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)

pip-tools:打造可重复、可控的 Python 开发环境,解决依赖关系,让代码更稳定

在 Python 开发中,管理依赖关系是一项繁琐且容易出错的任务。手动更新依赖版本、处理冲突、确保一致性等等,都可能让开发者感到头疼。而 pip-tools 为开发者提供了一套稳定可靠的解决方案。 什么是 pip-tools? pip-tools 是一组命令行工具,旨在简化 Python 依赖关系的管理,确保项目环境的稳定性和可重复性。它主要包含两个核心工具:pip-compile 和 pip

【VUE】跨域问题的概念,以及解决方法。

目录 1.跨域概念 2.解决方法 2.1 配置网络请求代理 2.2 使用@CrossOrigin 注解 2.3 通过配置文件实现跨域 2.4 添加 CorsWebFilter 来解决跨域问题 1.跨域概念 跨域问题是由于浏览器实施了同源策略,该策略要求请求的域名、协议和端口必须与提供资源的服务相同。如果不相同,则需要服务器显式地允许这种跨域请求。一般在springbo

题目1254:N皇后问题

题目1254:N皇后问题 时间限制:1 秒 内存限制:128 兆 特殊判题:否 题目描述: N皇后问题,即在N*N的方格棋盘内放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在同一斜线上。因为皇后可以直走,横走和斜走如下图)。 你的任务是,对于给定的N,求出有多少种合法的放置方法。输出N皇后问题所有不同的摆放情况个数。 输入

C++ | Leetcode C++题解之第393题UTF-8编码验证

题目: 题解: class Solution {public:static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num &