python之编码和解码

中国程序员始终绕不过的的坑大概就是编码问题了,无数次的中文乱码总是令人头疼!!!

虽然说了很多遍但还还是重复一遍解释中文乱码的原因吧

最先出场的就是ASCII码了,美帝人民发明计算机后,把英文26个字母和常用的符号加起来也就百来个字符,用1字节8位(0-255)一一映射也就绰绰有余了,
之后随着计算机的发展,各国需要显示本土的文字也一一发明了自己的编码表。
然后出场的便是ISO了,本着先来后到的原则,欧洲人接触到计算机后,在ASCII中把德语法语等非英语的字符也塞进了空余的为之中,美国人编码才用了7个字节,再塞下德语法语之后终于把第八个字节也用上了
随后就是GBK了,计算机传到中国后,面对中文的博大精深,一个字节实在难以满足需求,于是gbk使用了两个字节来表示中文,同时也为了兼容ASCII,在第一位设置为标志位,如果为0 只一字节,ascii 剩下7个字节就可以表示了,为1则是读两个字节映射中文。
所以在任何时候英文都不会乱码的原因就是之后的编码表都是在兼容ASCII码上设计的。
但是这样各国之间的数据便不互通了,最终国际组织站出来了,使用了6个字节将全世界的语言都映射成一张编码表,这就是unicode码了,但在讲究效率的年代明明一个字节表示的字符(如ascii码),前面非要再传5个 00000000 的字节实在是浪费,所以之后人们有规定了边长码传输unicode码的协议,这边有了utf-7,utf-8,utf-16等等协议
而我们现在最常用的便是utf-8了,他的编码规则是:如果只有一个字节则其最高二进制位为0;如果是多字节,其第一个字节从最高位开始,连续的二进制位值为1的个数决定了其编码的字节数,其余各字节均以10开头。UTF-8转换表表示如下:

Unicode符号范围 | UTF-8编码方式
(十六进制) | (二进制)
--------------------+---------------------------------------------
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
1个字节时:第一位为0后7位表示数据
大于1个字节时:第一个字节在0之前有几个1就表示这个字符用了几个字节表示,后面的字节都以10开头

所有有效表示unicode编码的数据都是在一个字节读取0后开始计算的,所以2个字节utf-8编码能表示11位的Unicode编码....

unicode只是一张映射表,把世界所有的字符都映射了,而utf-8只是unicode编码传输时的一种实现

再来说说python中编码的问题

在python2时代 字符串和字节没有很好的区分,在python3中将两种完全分开为字符串str和字节bytes,str即是unicode编码,而byte则是真正的二进制,只是用了16进制形式表现: \xe4,
但你可能会问 Unicode 只是一张编码表,人为定义了二进制的每个值等于对应的字符啊,其根本他也是一串二进制。对的,但这就是python的机制,对于字符串str在从内存读到显示器上时,python自动完成了解码工作让你看到的不是一串二进制,而是这串二进制根据unicode对应的字符,但对于字节bytes来说,python不会对他处理,就这么原汁原味的呈现给你,所以你看到的str是字符串而bytes则是16进制表示的二进制。
那为什么有时候python里的字符串会是乱码呢,那是因为python自动对unicode解码的规则是utf-8,如果原本字符串的二进制不是unicode码那么解码过后自然就是乱码了

encode和decode

对于字符串str只有一个编码方法 .encode()默认是以utf-8编码,生成的是对应的字节bytes。也即是告诉python,str不需要自动编码了,就以二进制显示。
对于字节bytes只有一个解码方法.decode()默认也是utf-8解码,生成对应的字符串str。也就是相当于告诉python,将我解码后再显示出来,就不再是二进制的形式了。
当然编解码都可以以指定的格式编解码,类似 .encode('gbk') 。

Snipaste_2018-11-01_09-46-53.jpg

unicode的编解码

有时我们还会遇到以\u开头的字节 ,例如 b'\u4e2d' , 这表示的是这是一个原生Unicode字节(注意unicode和utf-8的字节是不一致的 ,前文已经说过了),所以以默认的utf-8编码去对这种unicode是不能正确解码的,我们需要使用特定的unicode_escape解码格式才能正确解码。

b'\u4e2d'.decode('unicode_escape')

同理你也可以以unicode_escape编码,将一个字符串转化为原生的unicode字节

总结

如果你还是有些迷糊,那你可以记住 str是python自动帮你解码后给你呈现的字符串 ,bytes是直接给你看到二进制字节,无论str还是bytes在python里本质都是unicode编码。当然这也是我个人的理解,可能会存在偏差,欢迎各位互相交流

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容