关于编码的概述究源

[专题] 2024-04-30 圈点477

摘要:在计算机中,最重要的也是最麻烦的问题,莫过于编码了。下面就研究研究编码问题。

 在计算机中,最重要的也是最麻烦的问题,莫过于编码了。下面就研究研究编码问题。


1,二制度:

但凡在计算机中存储的数据(声音,图片,动画,文字...),在本质上,都是按照1与0这样的排列组合的形式存储的。


2,ASCII

“阿斯克”码,英文ASCII,其共有128个字符的编码,包含这128个符号中, 0~31及127(共33个)是控制字符或通信字符,32–126 分配给了能在键盘上找到并且能打印出来的字符。所有ASCII编码表示的内容,只占用了一个字节的后面7位,最高位统一规定为0。即01000000.


扩展:后来为了能够表示欧洲地区除了英文字母以外的其它字母,出现了扩展的ASCII编码。 扩展的ASCII包含原有的128个字符,又增加了128个字符,总共是256个。编码时最高位为1,这样就可以与ASCII码完全兼容。可以表示诸如音标æ(编码145,二进制10010001)以及法语中的字母é(编码为130,二进制10000010)等字符。这个编码能表示音标和欧洲大多数非英语系字母,但是它并不是国际标准,在不同的国家, 128 到 255对应的字符并不完全相同,这就产生了各种不同的扩展ASCII编码。比如 ISO8859-1 字符集,也就是 Latin-1,加入了西欧常用字符,包括德法两国的字母。ISO8859-2 字符集,也称为 Latin-2,收集了东欧字符。 ISO8859-3 字符集,也称为 Latin-3,收集了南欧字符,等等。


这样的编码方式够吗?显然不够,比如汉字,就无法用ASCII表示。扩展的ASCII 也远远不够。


3,GBK


GBK编码一般用两个字节表示一个字符,如果是英文字母,则使用一个字符,与ASCII编码相同,因此,GBK 也是兼容 ASCII 编码的,但并不与任何扩展的ASCII编码兼容。这可以从它的编码序列看出来。


GBK 采用双字节表示,总体编码范围为 0x8140-0xFEFE(1000000101000000-1111111011111110),首字节在 0x81-0xFE 之间,尾字节在 0x40-0xFE之间。可以看出首字节最高位都为1,这样一来,如果尾字节后的字节最高位为0,那么就可以解析为一个ASCII编码字符,否则就是一个连续的二字节字符。


中国人为了能够正常使用计算机这一伟大方明,做出了多方面的努力。GB2312就是这一努力的成果, 该标准于1980年发布,1981年5月1日开始实施。它标志着我国在使用电子计算机方面迈出了重要的一步。GB2312 编码共收录了6763个汉字,同时还兼容 ASCII。这一字符编码基本满足了汉字的计算机处理需要,它所收录的汉字已经覆盖中国大陆99.75%的使用频率,对一些古汉语和繁体字 GB2312 没法处理。后来就在GB2312的基础上创建了一种叫 GBK 的编码,于1995年正式发布。GBK 不仅收录了GB 2312 中的全部汉字、非汉字符号,同时还收录了日韩语中出现的汉字,如韩国著名围棋手李世乭中的乭 GBK编码是0x8168(0x表示16进制)



4,Unicode


世界上存在着多种语言,有没有一种编码方式能够囊括所有语言中的字符呢?答案是有。Unicode编码正是为了满足这种需求制定的。Unicode是一个很大的集合,目前的规模可以容纳100多万个符号。每个符号的编码都不一样,这么多的字符,想要以二进制形式表示,就需要比较多的字节才能够一一对应。标准的Unicode采用4个字节表示一个字符串。这个四字节的二进制代码,称为这个字符的码点。比如,U+0639表示阿拉伯字母Ain,U+0041表示英语的大写字母A,U+ 4E6D表示汉字"乭 "。访问unicode.org可以查询具体的符号对应表。


使用4个字节表示一个字符的方法显然不够科学,因为很多英文字母只需要一个字节就可以表示了,偏要用四个字节表示就会造成很大的浪费。于是就出现了UTF-8 编码。


Unicode只是规定了字符如何编码,并没有规定如何存储和传输。 UTF-8编码就是Unicode编码的一种实现方式,它规定可以使用1~4个字节表示一个字符,根据所要表现的字符不同而变化字节长度,英文字母就用1个字节表示,汉字就用2-3个字节表示。


那么问题来了,由于计算机中的字符串是连续的0101的编码,如何既能够表示一个字符在Unicode编码表中的码点,又能够让计算机明白这个连续编码串中的一个字节就是一个英文字母,而不与他前面的编码串构成两个或三个字节表示的字符。UTF-8 的编码的设计者巧妙的解决了这个问题。


英文字符这些原本就可以用ASCII码表示的字符用UTF-8表示时就只需要一个字节的空间,和ASCII是一样的。对于多字节(n个字节)的字符,第一个字节的前n为都设为1,第n+1位设为0,后面字节的前两位都设为10。剩下的二进制位全部用该字符的Unicode码填充。


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


这样的编码方式很好理解,如果一个字节当中第一位是0,那么这个字节就对应着一个字符,如果第一位是1,那么看他后面连续有多少个1,就表示这个字符占用了多少个字节。例如,“我”的Unicode码点是0x6211,二进制110001000010001,落在第三行的范围内(0000 0800~0000 FFFF),因此"我"需要三个字节,格式是"1110xxxx 10xxxxxx 10xxxxxx"。然后,从"我"的最后一个二进制位开始,依次从后向前填入格式中的x,多出的位补0。这样就得到了"我"的UTF-8编码是"11100110 10001000 10010001 ",转换成十六进制就是E68891,这才是最终存储在计算机中的二进制编码。


这里指出一个误区,网络上有很多在线utf8编码转换工具,声称可以把汉字转换成UTF-8 编码,其实大多数工具只是把汉字转换成了与之对应的unicode码点,并不是真正在存储和传输过程中的utf-8编码。


除了UTF-8之外,Unicode的实现方式还有UTF-16 ,UTF-32 。 UTF-16 使用2~4个字节表示一个字符,UTF-32 则使用标准的4个字节表示一个字符,与其Unicode码点一一对应。无论采用哪种表现形式,同一字符所对应的Unicode码点都是一样的,只不过在存储和传输的时候,把码点做了不同的转换。

编码  

感谢反馈,已提交成功,审核后即会显示