unicode,utf-8,ASCLL计算机编码原理

一、字符编码问题
先介绍一下字符编码问题

1.ASCLL与GB2312

由于计算机是美国人发明的,因此,最早只有127个字符被编码到计算机里,也就是大小写英文字母、数字和一些符号,这个编码表被称为ASCII编码,比如大写字母A的编码是65,小写字母z的编码是122。

但是要处理中文显然一个字节是不够的,至少需要两个字节,而且还不能和ASCII编码冲突,所以,中国制定了GB2312编码,用来把中文编进去。

国标码是汉字的国家标准编码,目前主要有GB2312、GBK、GB18030三种。

GB2312编码方案于1980年发布,收录汉字6763个,采用双字节编码。
GBK编码方案于1995年发布,收录汉字21003个,采用双字节编码。
GB18030编码方案于2000年发布第一版,收录汉字27533个;2005年发布第二版,收录汉字70000余个,以及多种少数民族文字。GB18030采用单字节、双字节、四字节分段编码。
新版向下兼容旧版,也就是说GBK是在GB2312已有码位基础上增加新码位,GB18030是在GBK已有码位基础上增加新码位,各种编码方案中共有的字符编码相同。现在的中文信息处理应优先采用GB18030编码方案。

2.Unicode

全世界有上百种语言,日本把日文编到Shift_JIS里,韩国把韩文编到Euc-kr里,各国有各国的标准,就会不可避免地出现冲突,结果就是,在多语言混合的文本中,显示出来会有乱码。因此,Unicode应运而生。Unicode把所有语言都统一到一套编码里,这样就不会再有乱码问题了。Unicode标准也在不断发展,但最常用的是用两个字节表示一个字符(如果要用到非常偏僻的字符,就需要4个字节)。

ASCLL与Unicode的关系

现在,捋一捋ASCII编码和Unicode编码的区别:ASCII编码是1个字节,而Unicode编码通常是2个字节。

字母A用ASCII编码是十进制的65,二进制的01000001;

字符0用ASCII编码是十进制的48,二进制的00110000,注意字符‘0‘和整数0是不同的;

汉字‘中‘已经超出了ASCII编码的范围,用Unicode编码是十进制的20013,二进制的01001110 00101101。

你可以猜测,如果把ASCII编码的A用Unicode编码,只需要在前面补0就可以,因此,A的Unicode编码是00000000 01000001。

3.UTF-8

UTF-8编码把一个Unicode字符根据不同的数字大小编码成1-6个字节,常用的英文字母被编码成1个字节,汉字通常是3个字节,只有很生僻的字符才会被编码成4-6个字节。如果你要传输的文本包含大量英文字符,用UTF-8编码就能节省空间。

ASCLL与utf-8编码的关系

字符 ASCII Unicode UTF-8
A 01000001 00000000 01000001 01000001
中 x 01001110 00101101 11100100 10111000 10101101
从上面的表格可以发现,UTF-8编码有一个额外的好处,就是ASCII编码实际上可以被看成是UTF-8编码的一部分,所以,大量只支持ASCII编码的历史遗留软件可以在UTF-8编码下继续工作。

计算机系统通用的字符编码工作方式

搞清楚了ASCII、Unicode和UTF-8的关系,我们就可以总结一下现在计算机系统通用的字符编码工作方式:

在计算机内存中,统一使用Unicode编码,当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编码。

用记事本编辑的时候,从文件读取的UTF-8字符被转换为Unicode字符到内存里,编辑完成后,保存的时候再把Unicode转换为UTF-8保存到文件。

str与bytes,encode() 与 decode()

Python的字符串类型是str,在内存中以Unicode表示,一个字符对应若干个字节。如果要在网络上传输,或者保存到磁盘上,就需要把str变为以字节为单位的bytes。Python对bytes类型的数据用带b前缀的单引号或双引号表示:

x = b‘ABC‘
要注意区分‘ABC‘和b‘ABC‘,前者是str,后者虽然内容显示得和前者一样,但bytes的每个字符都只占用一个字节。bytes类型中把单个字节能显示的字符显示,不能显示的用\x##。

以Unicode表示的str通过encode()方法可以编码为指定的bytes,例如:

>>> ‘ABC‘.encode(‘ascii‘)
b‘ABC‘
>>> ‘中文‘.encode(‘utf-8‘)
b‘\xe4\xb8\xad\xe6\x96\x87‘
>>> ‘中文‘.encode(‘ascii‘)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: ‘ascii‘ codec can‘t encode characters in position 0-1: ordinal not in range(128)
 纯英文的str可以用ASCII编码为bytes,内容是一样的,含有中文的str可以用UTF-8编码为bytes。含有中文的str无法用ASCII编码,因为中文编码的范围超过了ASCII编码的范围,Python会报错。

在bytes中,无法显示为ASCII字符的字节,用\x##显示。(b‘ABC‘可以显示为ASCLL字符的字节,b‘\xe4\xb8\xad\xe6\x96\x87‘无法显示为ASCLL字符的字节)

反过来,如果我们从网络或磁盘上读取了字节流,那么读到的数据就是bytes。要把bytes变为str,就需要用decode()方法:

>>> b‘ABC‘.decode(‘ascii‘)
‘ABC‘
>>> b‘\xe4\xb8\xad\xe6\x96\x87‘.decode(‘utf-8‘)
‘中文‘
 如果bytes中包含无法解码的字节,decode()方法会报错,如果bytes中只有一小部分无效的字节,可以传入errors=‘ignore‘忽略错误的字节:

>>> b‘\xe4\xb8\xad\xff‘.decode(‘utf-8‘)
Traceback (most recent call last):
...
UnicodeDecodeError: ‘utf-8‘ codec can‘t decode byte 0xff in position 3: invalid start byte
>>> b‘\xe4\xb8\xad\xff‘.decode(‘utf-8‘, errors=‘ignore‘)
‘中‘
 可见,1个中文字符经过UTF-8编码后通常会占用3个字节,而1个英文字符只占用1个字节。

在操作字符串时,我们经常遇到str和bytes的互相转换。为了避免乱码问题,应当始终坚持使用UTF-8编码对str和bytes进行转换。

二、问题解决
现在看遇到的问题

df = pd.read_csv(‘catering_sale.csv‘)
然后出现了

UnicodeDecodeError: ‘utf-8‘ codec can‘t decode byte 0xc8 in position 0: invalid continuation byte
 pd.read_csv():

encoding : str, default None

Encoding to use for UTF when reading/writing (e.g. ‘utf-8‘). List of Python standard encodings

默认的encoding 是utf-8,所以问题是出现了utf-8不能解码的字节。

该情况是由于出现了无法进行转换的 二进制数据造成的,可以写一个小的脚本来判断下,是整体的字符集参数选择上出现了问题,还是出现了部分的无法转换的二进制块:

#python3
#以读入文件为例:
f = open("catering_sale.csv","rb")#二进制格式读文件
i = 0
while True:
  i += 1
  print(i)
  line = f.readline()
  if not line:
    break
  else:
    try:
     # print(line)
     # print(line.decode(‘utf8‘))
     line.decode(‘utf8‘)
      #为了暴露出错误,最好此处不print
    except:
      print(str(line))
输出

1
b‘\xc8\xd5\xc6\xda,\xcf\xfa\xc1\xbf\r\n‘
2
3
4
5
6
从输出中可以看出是第一行中的字节编码无法解码。这是可以看自己的第一行数据。我的情况是中文。

找到了问题,尝试了一下修改方法:

使用国标码编码

df = pd.read_csv(‘catering_sale.csv‘, encoding = ‘gb2312‘)

读取时也可以用二进制模式打开的文件(包括模式参数中的‘b‘)将内容作为字节对象,而不进行任何解码。

然后使用line.decode(‘gbk’)解码,其中的errors参数:

修改字符集参数,一般这种情况出现得较多是在国标码(GBK)和utf8之间选择出现了问题。
出现异常报错是由于设置了decode()方法的第二个参数errors为严格(strict)形式造成的,因为默认就是这个参数,将其更改为ignore等即可。
————————————————
版权声明:本文为CSDN博主「Rookiekk」的原创文章,遵循 CC 4.0 BY-SA 版权协议。
原文链接:https://blog.csdn.net/qq_18888869/article/details/82625343

原文地址:https://www.cnblogs.com/windtalk/p/11660759.html

时间: 2024-10-06 03:31:59

unicode,utf-8,ASCLL计算机编码原理的相关文章

ascii、unicode、utf、gb等编码详解

很久很久以前,有一群人,他们决定用8个可以开合的晶体管来组合成不同的状态,以表示世界上的万物.他们看到8个开关状态是好的,于是他们把这称为"字节".再后来,他们又做了一些可以处理这些字节的机器,机器开动了,可以用字节来组合出很多状态,状态开始变来变去.他们看到这样是好的,于是它们就这机器称为"计算机". 开始计算机只在美国用.八位的字节一共可以组合出256(2的8次方)种不同的状态. 他们把其中的编号从0开始的32种状态分别规定了特殊的用途,一但终端.打印机遇上约定

字符编码原理 ASCII,Unicode和UTF-8

字符编码笔记:ASCII,Unicode和UTF-8 今天中午,我突然想搞清楚Unicode和UTF-8之间的关系,于是就开始在网上查资料. 结果,这个问题比我想象的复杂,从午饭后一直看到晚上9点,才算初步搞清楚. 下面就是我的笔记,主要用来整理自己的思路.但是,我尽量试图写得通俗易懂,希望能对其他朋友有用.毕竟,字符编码是计算机技术的基石,想要熟练使用计算机,就必须懂得一点字符编码的知识. 1. ASCII码 我们知道,在计算机内部,所有的信息最终都表示为一个二进制的字符串.每一个二进制位(b

[转]utf8编码原理详解

from : http://blog.csdn.net/baixiaoshi/article/details/40786503 很久很久以前,有一群人,他们决定用8个可以开合的晶体管来组合成不同的状态,以表示世界上的万物.他们认为8个开关状态作为原子单位很好,于是他们把这称为"字节". 再后来,他们又做了一些可以处理这些字节的机器,机器开动了,可以用字节来组合出更多的状态,状态开始变来变去.他们看到这样是好的,于是它们就这机器称为"计算机". 开始计算机只在美国用.

BASE64编码原理分析脚本实现及逆向案例

BASE64编码原理分析脚本实现及逆向案例 0x01 简单介绍 数据传送时并不支持所有的字符,很多时候只支持可见字符的传送.但是数据传送不可能只传送可见字符为解决这个问题就诞生了base64编码.base64编码将所有待编码字符转换成64个可见字符表中的字符. 0x02 编码原理 被Base64编码之后所得到的所有字符都是在以下这个表当中的. 上表中总共有64个字符,2^6=64所以只需要6个bit位就足够描述所有的表中字符了.计算机中1个字节8个bit,一个ASCII码占1个字节.因此多出来的

计算机 编码 解码

目录 1 字符 & 编码 2 记事本下的乱码 3 UTF-8解码过程 4 UTF-16解码过程 5 ISO-8859-1 6 byte范围 在阅读本文章之前,我建议你首先看阮一峰的博客:http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html 1 字符 & 编码 字符: 是文字和符号的总称.一个汉字.标点符号.英文字母.数字,这都是字符 字符集: 是多个字符的集合.我们可以理解为一本大字典.字符集种类很多,每个字

Qt实现16进制unicode转utf-8以及国际音标编码问题

由于项目需要,需要对网络资源进行解码.遇到编码问题.研究了下基本编码原理.于是有了下面两个通用代码 [cpp] view plaincopy 1. 16进制unicode转换为utf-8中文显示 QString unicodeToUtf_8(const QString &resStr) { //  unicode转utf-8  思路: 一个unicode编码占用2字节.所以只需要用4个16进制数字结合表示就行了 QString temp; for (int i = 0; i< resStr.

关于计算机编译原理

从我个人理解,计算机编译原理,顾名思义,就是关于计算机编程翻译的相关原理,即对计算机编程的,更为深入.更为详细的去解读计算机语言.上网看了许多个人解读编译原理,发现最令我信服的,就是把编译原理类比成人体解剖:只有认真解剖.研究人体各部位,才能在手术中.医治中做到更好的处理.因此,唯有理解编译原理,才能更好地进行计算机的编程等一系列的操作. 博客上有人说到,学习编译原理能够更加容易理解算法之间的关系.能培育自己的观点.提高学习语言的效率.但在我个人看来,学好编译原理,能让我们有一个更强的临时变换的

Atitit.Base64编码原理与实现设计

Atitit.Base64编码原理与实现设计 1. Base64编码1 1.1. 为什么要用自己的base64编码方案1 2. Base64编码由来1 3. Base64编码原理1 3.1. 具体来说,转换方式可以分为四步:2 3.2. 注意2 3.3. Padding3 4. URL安全的Base64编码3 1. Base64编码 1.1. 为什么要用自己的base64编码方案 防止apache codec  jdk的jar冲突. 2. Base64编码由来 Base64最早是用来解决电子邮件

Linux内核设计第一周 ——从汇编语言出发理解计算机工作原理

Linux内核设计第一周 ——从汇编语言出发理解计算机工作原理 作者:宋宸宁(20135315) 一.实验过程 图1 编写songchenning5315.c文件 图2 将c文件汇编成32位机器语言 图3 将.s文件中的链接语句删除,获得最后的汇编代码 二.分析堆栈变化情况 三.总结 阐明对“计算机是如何工作的”的理解. ①计算机是依据冯诺依曼体存储结构,依据其核心思想——存储程序计算机工作模型,按程序编排的顺序,一步一步地取出指令,自动地完成指令规定的操作. ②从硬件的角度看,是通过总线连接C