我对编码的理解
在我之前的编程生涯中,总是对一些关键概念糊里糊涂不求甚解,比如进程、线程,比如堆、栈、编码。我对这很
在我之前的编程生涯中,总是对一些关键概念糊里糊涂不求甚解,比如进程、线程,比如堆、栈、编码。我对这很多概念的理解,都来自于各式样的博客。
最近几年看书多些,了解到最好的学习方式是将获得的知识以自己熟悉的模式进行整理(那许多的博客,是他人对自己知识的整理;当然,有一些文章,是将知识融会贯通后发明的“新招式”),于是逼着自己一个月整理一篇技术博客。
最近正阅读的技术书籍有Effective Python、《编码》,它们都提到编码、字符集、ASCII、Unicode、UTF-8、str、bytes……等相关关键字。
(资料图片)
在我理解“编码”时,再一次地产生晦涩感,于是4月的技术整理,是“我对编码的理解”。(我承认五一假期一直在玩耍,这篇文章,该在上周就整理完毕的。)
这个世界,是先有文字然后才有计算机的。所以计算机展示文字(以“嘟”字举例)的方式,简单点说,可以是:将一张“嘟”字的图片放到屏幕上展示。
这句话可以拆成两个问题:
如何拿到图片?
如何在屏幕上展示图片?
“如何在屏幕上展示图片”并非理解编码的重点,我只提供两个思考方向:
一是在《编码》中看到的。视频适配板有一个字符生成器(character generator),在生产时就包含了所有的ASCII码字符的8x8像素图。每当需要展示字符(以“A”举例)时,先找到“A”的ASCII码0x41
,再通过0x41
找到存储在字符生成器中的像素图,再依据像素图将对应位置的像素点进行点亮。
二是来自OpenGL学习文档中的FreeType:使用矢量图像构造字形。大家感兴趣可以查看后面的引用链接。(该文档中“位图字体”与《编码》中思想一致,都是直接展示图片。)
本篇文章的重点是如何拿到图片?
如何拿到图片呢?
为回答这个问题,我们首先得知道“图片”是什么?
如上所说,图片是“文字”,是人类用来纪录特定事物、简化图像而成的书写符号(后文称“书写符号”为“字符”)。
全球有近200个国家,约6000种语言,人类主要使用的文字种类有:语素文字、音节文字、拼音文字等。其中以英语、汉语、印地语、西班牙语、法语、阿拉伯语、孟加拉语……等使用人数最多。
按照我从网上搜到的统计数字:全世界所有的字符数量是超过10万个的。
如果计算机需要将这10万多个字符都展示出来,则相应的需要10万多张图片?
这些图片如何管理,字符“A”是排在字符“嘟”前面还是后面?中文、英文、法语、俄语甚至日语需要放在一起么?我是中国人,看不懂也用不上俄语,需要去设置去关心俄语图片么?
计算机起源于美国,最初的科学家确实是只关注英文的,于是设定了ASCII(American Standard Code for Information Interchange)标准——26个字母、阿拉伯数字,再加上些标点符号,够了!
随着计算机向全球普及,ASCII收录的字符显然是不够用的,于是各个国家出台自己的标准——比如Shift-JIS(日本工业标准)、GB2312(中国标准简体中文字符集)等——来表示本国的文字。
同一事物的标准越多,则代表没有标准;多标准一起存在,乱码处处可见。
为了统一标准,1988年,几大著名计算机公司合作研究出一种用来替代ASCII码的编码系统,取名为Unicode(统一化字符编码标准),它采用16位编码,每一个字符需要2个字节,可以表示65535个不同字符。全世界所有的人类语言,都使用同一个编码标准。(后来,Unicode再次扩容,分为17个面,即一共可以表示17 * 65535 = 1114095
个字符。一般情况下只需要0号平面就够了。)
到此处,则可以回答节首的问题:如何拿到图片呢?
从Unicode中拿!
Unicode是什么呢?
Unicode是字符集,是一种标准,是收录全世界字符图片并为之配上一个编号的标准。比如字符“A”的编号是0x41
,“嘟”的编号为0x561F
(本文的编号,都是16进制)。
如上所说,现在我们知道了文字字符,是一个编号对应一张图片,这所有的对应关系合在一起成为了Unicode字符集。
在计算机在进行数据传输与存储时,为了节省空间,是只会传输和存储字符编号的。
如何存这个编号?是我们需要关注的重点。
对ASCII码来说,一个字符,一个字节就够了,挨着存就好:比如Hello
的存储形式为48 65 6C 6F 2C
。
当标准切换为Unicode时,一个字符的编号需要两个字节长度来存储,以Hello
加个嘟嘟
举例,它的存储形式将变成00 48 00 65 00 6C 00 6F 00 2C 00 20 56 1F 56 1F
(空格字符的编号为0x20
)。
我们可以看到,中间是有很多空间被浪费的,很多的00
不需要被存下来。
为了去掉这些额外空间,大佬们又为Unicode编码发明了UTF-8(8-bit Unicode Transformation Format)
,一种针对Unicode的可变长度字符编码。
具体的UTF-8规则此文不再阐述,我只在Python3中向大家展示一下如何将UTF-8编码转回Unicode编号:
# 1. 原字符串>>> s = 'Hello 嘟嘟'# 2. 将其以UTF-8格式进行编码(encode函数,默认参数是utf-8)>>> b = s.encode()>>> bb'Hello \xe5\x98\x9f\xe5\x98\x9f'# 3. 将编码出来的bytes对象以16进制展示>>> b.hex()'48656c6c6f20e5989fe5989f'# 4. 将“嘟”字的UTF-8码以二进制形式展示出来>>> dudu = '嘟'>>> [bin(byte) for byte in bytes(dudu, 'utf-8')]['0b11100101', '0b10011000', '0b10011111']
可以看到,上面实例第3点,当将Hello 嘟嘟
的UTF-8展示形式以16进制展示出来时,是没有额外存储0x00
的。
末尾“嘟”的UTF-8存储形式为e5989f
,在我将其以二进制形式展示出来后,套入UTF-8的规则进行逆解。
由上面的表格可以看到,只需要将第1个字节的后4位0101
、第2个字节的后6位011000
、第3个字节的后6位011111
进行拼接,即能得到Unicode的编码,见证奇迹的时刻到了……
拼接之后的二进制码为:
# 1. 将拼接好的二进制码赋值给int>>> b1 = int('01010110', 2)>>> b2 = int('00011111', 2)# 2. 将int转成16进制展示>>> hex(b1)'0x56'>>> hex(b2)'0x1f
可以看到,将“嘟”字转回为Unicode编号之后,与我们查表得来的0x561F
是一致的。
所以,UTF-8是什么呢?UTF-8只是一种存储Unicode编号的方式。
综上所述,我算是对与文字相关联的那些关键字——字符集、ASCII、Unicode、UTF-8、str、bytes——有些了解了。
文字是什么?文字是一张张图片,是人类用来纪录特定事物、简化图像而成的书写符号。
字符集是什么?字符集是一种标准,一种规范,一种协议,一种整理统计文字图片及图片所对应编号的一种集合。ASCII、Unicode、GBK等都是字符集。
UTF-8是什么?是存储Unicode字符集里面文字编号的一种字节编排方式。
str、bytes是什么?是Python3中的两种类型,可以很笼统地将str与Unicode对应,将bytes与UTF-8对应。
GBK,国家标准扩展。在Python3里面可以直接以gbk
形式对str对象进行编码,这理解起来会简单些:
# 将str以gbk编码转为bytes>>> s = 'Hello 嘟嘟'>>> s.encode('gbk')b'Hello \xe0\xbd\xe0\xbd'
可以看到“嘟”字的存储形式为0xE0BD
,占用2个字节,看下方截图,直接就找到映射关系了。
下面链接中“%”符号后面跟着的两个字符,也是Unicode编号以UTF-8形式进行编码的。可以按照上面的逆解方式验证。
1、Unicode码表:https://zh.wikipedia.org/wiki/Unicode%E5%AD%97%E7%AC%A6%E5%88%97%E8%A1%A8(解出来的中文是“字符列表”)
2、GBK码表:https://toolhelper.cn/Encoding/GBK
3、OpenGL的文字渲染:https://learnopengl-cn.readthedocs.io/zh/latest/06%20In%20Practice/02%20Text%20Rendering/
4、文字分类:https://zh.wikipedia.org/wiki/%E6%96%87%E5%AD%97
5、UTF-8的编码方式:https://zh.wikipedia.org/wiki/UTF-8#UTF-8%E7%9A%84%E7%B7%A8%E7%A2%BC%E6%96%B9%E5%BC%8F
标签:
在我之前的编程生涯中,总是对一些关键概念糊里糊涂不求甚解,比如进程、线程,比如堆、栈、编码。我对这很
1、长城不太稳固。2、其实和联通的差不多。3、建议你不要用长城。本文到此结束,希望对大家有所帮助。
近3年白云山涨幅最少,想象空间大,大南药毛利率并不低。$白云山(SH600332)$$同仁堂(SH600085)$$广誉远(SH6
观点网讯:5月28日,福州市人民政府消息称,经过前期设计和完善,福州三宝城的地标建筑——三宝中心项目规
东方网5月28日报道:为持续推进本区数字化建设,引领数字化生活新风尚,今天上午,2023年崇明区数字化成果体
如果说在2023永劫无间春季赛单排赛中,表现非常亮眼的选手,那无疑就是直接晋级总决赛的几位选手,比如说“
这是一部我没看懂的电影,影片只有四十分钟,导演寺山修司,电影名为《草迷宫》。在日本寺山修司被称为奇人
1、高远,1933年出生,是香港凤凰影业公司著名的 "英俊小生 "。2、原名蒋家琪,江苏苏州人。本文到此分享完
[ 相关新闻 ]