[理解]ASCII和Unicode和UTF-8编码问题

在编程当中,多会遇到不同编码导致的乱码问题。这个问题这里记录一下,希望能终结这个问题:
(部分来自网络,更多的是自己的理解,所以标题,不是原创而是理解,侵删)

ASCII码:老美提出来的,0~127表示不同的英文字母,共7bit

多国码:法国俄罗斯等在ASCII的基础上,扩展集合成0~255。即ASCII还是用老美的不动,但是128 ~ 255各个国家定义自己的。

Unicode码:显然多国码有点扯淡,比如同样是128,在法国代表法文,在俄罗斯代表俄文,这不混乱了?怎么交流?因此,继续扩大集合,把所有国家的语言都放进来,编个号,一文字一个号,这下不乱了,这就是Unicode码

UTF-8码:看似Unicode解决了大问题,但是带来新问题:全世界那么多语言文字你都包含了,这个集合太大了。况且一个汉字根本无法用一个字节表征,好!扩大给你两字节,够不够?不够再加!那行,原来的ASCII码怎么办,老美只要一个字节就够了,现在让我前缀再补一个字节的零么?那我文件空间平白无故增加一倍?老美不干,Unicode迟迟无法推广。直到互联网交流日益密切,这个问题必须解决。有大佬提出用变长的编码行不行?行,我看行。

实现方法:在一个文本当中,所有的文字编码长度都不是固定的!

如果是字符只占1个字节,则最高位设为0,剩下的7位用来定义字符。
(即:0x0zzz_zzzz,这不就是ASCII码?现在ASCII加入了特殊字符,扩展到8位了,即256个。怎么办?往下看)

如果字符占据n字节(n>1),则首字节的最高位先放n个1,再跟个0,剩下的字节最高两位放10
(以n=2为例,即:0x110z_zzzz , 0x10zz_zzzz),可见两字节共有11bit的z可放,如果z用不完,则高位z补零,如果z不够用,把n增加1,继续放。

不失一般性,在UTF-8编码下,n字节可放z的bit数目位5n + 1。做个假设如果n = 7呢,则首字节被占满,z的bit数位36bit,2的36次方为:687_1947_6736。真心够用了。

话说大佬为什么这样定义?
A.靠首位的1区别了ASCII ,以0终止,1的个数描述了字符编码长度。不以0终止,那如果紧跟着的数据是1就会带来歧义

B.再靠后续的高位10延续本次编码,否则不知道后续的编码到底是不是新的开始

C.从B中描述,可以看出如果我就靠首字节1的数目来决定编码长度行不行?
比如0x110z_zzzz , 0xzzzz_zzzz。行,但是索引效率太低。如果某个数据编码就是1100_0000,1100_0000,在查阅文本的时候,就必须从文本起始位置才能确定这个是什么字符。因为你不能确定这两个1100_0000到底是属于一个字符还是分属不同字符。
如果采用UTF-8编码,1110_0000,1000_0000,1000_0000。这就很清楚,当看到10打头的时候,知道要往前索引找字长,直到发现1110_0000描述字长的字节,首字节找到,尾巴自然找到。按图索骥,一目了然,效率高。

猜你喜欢

转载自blog.csdn.net/ysgjiangsu/article/details/89312286