20201231-3 字符编码转换详解1

 
字符编码与转码
在2.7环境中咱们要写上这一行#-*- coding:utf-8 -*-  为什么我们要加这一行呢?这一样的意思是置顶编码类型为utf-8编码!
计算机本身只能识别 0  1 的组合
举个比较形象的例子,中英文词典对照表,这样我们就可以把中英文进行互相的翻译了
同理计算机也是这样的他需要一个标准的对照关系,ASCII表

这里在看个知识点:计算机中最小的单位是 bit  ;bit就是常说的一位二进制,一位二进制要么是0 要么是 1
但是bit这个单位太小了,我们用字节(byte)来表示。他们是有换算的规则的

8b = 1B  #小b=bit ; 大B=byte
1024B = 1KB
1024KB = 1M
1024M = 1G
1024G = 1T 

在存储英文的时候我们至少需要1个字节(一个字母),就是8位(bit),ASCII表中1个字节就可以表示所有的英文所需要的字符,只能存英文
1个字节8位,他能存储的最大数据是2的8次方-1 = 255,
一个字节最多能表示255个字符 那西方国家他们使用了127个字符,
那么剩下字符是做什么的呢?就是用来做扩展的,西方人考虑到还有其他国家。所以留下了扩展位。

如果仅仅支持英文的话,这127个字符完全就可以表示所有英文中能用的的内容了。
但是ASCII到了中国之后发现:咱们中国最常用的中文都有6000多个
但是怎们办?就在原有的扩展位中,扩展出自己的 gbk、gb2312、gb2318字符编码。

他是怎么扩展的?比如说在ASCII码中的128这个位置。这个位置又指定一张单独表, 其他国家也是这样设计的

比如韩国的游戏,在中国下载安装之后会出现乱码的情况。这种乱码的出现基本上就两种情况:
1、字符编码没有
2、字符编码冲突了,人家在写这个程序的时候指定的字符集和咱们使用的字符集的位置不对

基于这个乱象国际互联网组织就说你们各个国家都别搞了
我们给你们搞一个统一的,这个统一的是什么呢 Unicode“万国编码”

Unicode(统一码、万国码、单一码)是一种在计算机上使用的字符编码。
Unicode 是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,

规定字符和符号最少由 16 位来表示(2个字节),即:2 **16 = 65536 
注:此处说的的是最少2个字节,可能更多。

这里还有个问题:使用的字节增加了,那么造成的直接影响就是使用的空间就直接翻倍了
同样是ABCD这些字符存储一篇相同的文章
使用ASCII码如果是1M的话,那么Unicode存储至少2M可能还会更多。

为了解决个问题就出现了:UTF-8编码
UTF-8编码:是对Unicode编码的压缩和优化,他不再使用最少使用2个字节,
而是将所有的字符和符号进行分类:ascii码中的内容用1个字节保存、欧洲的字符用2个字节保存,
东亚的字符用3个字节保存...

通过这种可扩展的方式来存储。
回顾下乱码的出现原因:1、没有字符集 2、字符集冲突
不过这个问题在Python3中就不存在了,因为在Python3中默认就是Unicode编码

utf-8 可变长的,可伸缩的,所有的英文字符按ascii码处理; 所有的中文字符,统一的三个字节

# Python2.7 默认的编码是什么?
# 打印系统默认编码
import sys
print(sys.getdefaultencoding())
---> ascii
# 虽然程序是用 utf8 但默认编码是 ascii
# 如果没有 encode,会自动按系统编码 ascii 自动解码

1-1
s = "你好"
s_to_gbk = s.encode("gbk")
print(s_to_gbk)
print("你好")
--->
b'\xc4\xe3\xba\xc3'
你好

2-1
怎么解码呢?
s = "你好"
s_to_gbk = s.decode().encode("gbk")
print(s_to_gbk)
print("你好")
---> Error 
decode 如果不往里面传值,相当于用默认的编码;与没写是一样的
所以必须要显示的写进去

2-2
s = "你好"
s_to_unicode = s.decode("utf-8")
print(s_to_unicode)
s_to_gbk = s_to_unicode.encode("gbk")
print(s_to_gbk)

3-1
gbk_to_utf8 = s_to_gbk.decode("gbk").encode("utf-8")
print(gbk_to_utf8)
# gbk 转成 unicode  要告诉 unicode 之前是什么编码, 
# 然后 unicode 在去找和这个编码对应的并转成 unicode
# 然后在编码成 utf8

4-1
>>> s = "你好"
>>> s = u"你好"
>>> print(s)
你好
>>>    

# u 表示 unicode
# utf-8 是属于 unicode 的扩展集,unicode 是可以直接在 utf-8 中打印出来的
# 但是 gbk 不行,gbk 和 unicode 必须转换
# utf8 和 unicode 可以直接打印

4-2
如果 s 已经是 unicode了,所有的 decode 动作都是要解成 Unicode
如果已经是 unicode 了,解的时候就会报错

# 现在看看 Python 3
# 在 python3 中 不需要加 编码集
5-1
s = "你哈"
# 现在想要转成 gbk,默认就是 unicode,所以不需要解码,直接 encode
print(s.encode("gbk"))
---> b'\xc4\xe3\xb9\xfe'
# 现在右下角是默认编码 utf-8

5-2
# 如果把默认编码格式改为 gbk 呢?
s = "你哈"        # 注:默认 utf-8 编码
print(s.encode("gbk"))
--->
SyntaxError: Non-UTF-8 code starting with '\xc4' in file
# python3 默认是 unicode 所以无法处理 gbk,因为现在的这个文件是 gbk 编码的
# 所以是无法处理的,那应该怎么办呢?
# 需要声明,在文件头声明成 gbk

# -*- coding:gbk -*-
s = "你哈"
# 现在想要转成 gbk,默认就是 unicode,所以不需要解码,直接 encode
print(s)
print(s.encode("gbk"))
--->
你哈
b'\xc4\xe3\xb9\xfe'
# b表示 bytes;在python3 中,encode之后,除了修改编码集,会全部变成 bytes 类型,这是和 python2 最大的区别

6-1
s = "你哈"
s_gbk = s.encode("gbk")
print(s_gbk)
print(s.encode())
--->
b'\xc4\xe3\xb9\xfe'             # gbk
b'\xe4\xbd\xa0\xe5\x93\x88'     # utf-8

6-2
s = "你哈"
s_gbk = s.encode("gbk")
print(s_gbk)
print(s.encode())
gbk_to_utf8 = s_gbk.decode("gbk").encode("utf-8")
print("utf8",gbk_to_utf8)
# 先转成 unicode 在转成 utf8
--->
b'\xc4\xe3\xb9\xfe'
b'\xe4\xbd\xa0\xe5\x93\x88'
utf8 b'\xe4\xbd\xa0\xe5\x93\x88'   

# 所有的字符集转换都要经过一个 unicode
 
不管是 python2 还是 python3;不同编码之间的转换,首先要转换成 unicode 
utf-8 如果要转换成 gbk 要先 decode;decode 时 要告诉 unicode “我”是谁,比如这里就是 decode"utf-8"
这样就变成 unicode了。这时 如果要转换成 gbk,要先 encode 一下,encode时 写上 gbk
 
如果 更改了 python的默认编码格式。编码格式是什么,就需要声明什么,比如 #-*-coding:gbk-*-
不过,这个地方改的只是文件编码,文件是以 gbk 编码的
但是程序里面,python 默认就是 unicode,里面的字符串还是 unicode 
所以就没有 decode了,因为本身就是 unicode 
 
s = "你哈"; print(s.encode("gbk"));注意,右下角改的是文件编码,这个字符串还是 unicode 
打印结果是一个 bytes 类型,无法显示字符串;显示的只是 gbk 的编码格式

那么,可以直接 encode 成 utf-8 吗? 方式是一样的
print(s.encode("utf-8"))
print(s.encode("utf-8").decode())  
如果 decode 中不写,就是默认的 utf8,但还是写上比较好

如果想encode 成 gb2312 呢?
print(s.encode("utf-8").decode("utf-8").encode("gb2312"))
发现 gb2312 的格式 和 gbk 一样,因为 gbk 是向下兼容。所以编码和 gbk 是一样的

在 python3 中,encode时,不但转了编码,还变成了 bytes;decode 后,就变回了字符串
posted @ 2020-12-31 16:47  Malakh  阅读(248)  评论(1编辑  收藏  举报