关于字符集:字符编码原理

57次阅读

共计 2669 个字符,预计需要花费 7 分钟才能阅读完成。

ASCII 编码
在计算机外部,所有信息最终都是一个二进制值。每一个二进制位(bit)有 0 和 1 两种状态,因而八个二进制位就能够组合出 256 种状态,这被称为一个字节(byte)。也就是说,一个字节一共能够用来示意 256 种不同的状态,每一个状态对应一个符号,就是 256 个符号,从 00000000 到 11111111。

上个世纪 60 年代,美国制订了一套字符编码,对英语字符与二进制位之间的关系,做了对立规定。这被称为 ASCII 码,始终沿用至今。ASCII 码一共规定了 128 个字符的编码,比方空格 SPACE 是 32(二进制 00100000),大写的字母 A 是 65(二进制 01000001)。这 128 个符号(包含 32 个不能打印进去的管制符号),只占用了一个字节的前面 7 位,最后面的一位对立规定为 0

非 ASCII 编码
英语用 128 个符号编码就够了,然而用来示意其余语言,128 个符号是不够的。比方,在法语中,字母上方有注音符号,它就无奈用 ASCII 码示意。于是,一些欧洲国家就决定,利用字节中闲置的最高位编入新的符号。比方,法语中的é的编码为 130(二进制 10000010)。这样一来,这些欧洲国家应用的编码体系,能够示意最多 256 个符号。

然而,这里又呈现了新的问题。不同的国家有不同的字母,因而,哪怕它们都应用 256 个符号的编码方式,代表的字母却不一样。比方,130 在法语编码中代表了é,在希伯来语编码中却代表了字母 Gimel (ג),在俄语编码中又会代表另一个符号。然而不管怎样,所有这些编码方式中,0–127 示意的符号是一样的,不一样的只是 128–255 的这一段。

至于亚洲国家的文字,应用的符号就更多了,汉字就多达 10 万左右。一个字节只能示意 256 种符号,必定是不够的,就必须应用多个字节表白一个符号。比方,简体中文常见的编码方式是 GB2312,应用两个字节示意一个汉字,所以实践上最多能够示意 256 x 256 = 65536 个符号。

Unicode 编码
世界上存在着多种编码方式,同一个二进制数字能够被解释成不同的符号。因而,要想关上一个文本文件,就必须晓得它的编码方式,否则用谬误的编码方式解读,就会呈现乱码。为什么电子邮件经常呈现乱码?就是因为发信人和收信人应用的编码方式不一样。

如果有一种编码,将世界上所有的符号都纳入其中。每一个符号都给予一个举世无双的编码,那么乱码问题就会隐没。这就是 Unicode,就像它的名字都示意的,这是一种所有符号的编码。

Unicode 当然是一个很大的汇合,当初的规模能够包容 100 多万个符号。每个符号的编码都不一样,比方,U+0639 示意阿拉伯字母 Ain,U+0041 示意英语的大写字母 A,U+4E25 示意汉字严。具体的符号对应表,能够查问 unicode.org,或者专门的汉字对应表。

Unicode 的问题
Unicode 只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。

比方,汉字严的 Unicode 是十六进制数 4E25,转换成二进制数足足有 15 位(100111000100101),也就是说,这个符号的示意至多须要 2 个字节。示意其余更大的符号,可能须要 3 个字节或者 4 个字节,甚至更多。

这里就有两个重大的问题,第一个问题是,如何能力区别 Unicode 和 ASCII?计算机怎么晓得三个字节示意一个符号,而不是别离示意三个符号呢?第二个问题是,咱们曾经晓得,英文字母只用一个字节示意就够了,如果 Unicode 对立规定,每个符号用三个或四个字节示意,那么每个英文字母前都必然有二到三个字节是 0,这对于存储来说是极大的节约,文本文件的大小会因而大出二三倍,这是无奈承受的。

它们造成的后果是:1)呈现了 Unicode 的多种存储形式,也就是说有许多种不同的二进制格局,能够用来示意 Unicode。2)Unicode 在很长一段时间内无奈推广,直到互联网的呈现。

UTF-8 编码
互联网的遍及,强烈要求呈现一种对立的编码方式。UTF-8 就是在互联网上应用最广的一种 Unicode 的实现形式。其余实现形式还包含 UTF-16(字符用两个字节或四个字节示意)和 UTF-32(字符用四个字节示意),不过在互联网上根本不必。反复一遍,这里的关系是,UTF-8 是 Unicode 的实现形式之一。

UTF-8 最大的一个特点,就是它是一种变长的编码方式。它能够应用 1~4 个字节示意一个符号,依据不同的符号而变动字节长度。

UTF-8 的编码规定很简略,只有二条:

1)对于单字节的符号,字节的第一位设为 0,前面 7 位为这个符号的 Unicode 码。因而对于英语字母,UTF-8 编码和 ASCII 码是雷同的。

2)对于 n 字节的符号(n > 1),第一个字节的前 n 位都设为 1,第 n + 1 位设为 0,前面字节的前两位一律设为 10。剩下的没有提及的二进制位,全副为这个符号的 Unicode 码。

下表总结了编码规定,字母 x 示意可用编码的位。

http://github.crmeb.net/u/defu
Unicode 符号范畴 | UTF- 8 编码方式

(十六进制)(二进制)
0000 0000-0000 007F0xxxxxxx
0000 0080-0000 07FF110xxxxx 10xxxxxx
0000 0800-0000 FFFF1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

跟据上表,解读 UTF-8 编码非常简单。如果一个字节的第一位是 0,则这个字节独自就是一个字符;如果第一位是 1,则间断有多少个 1,就示意以后字符占用多少个字节。

上面,还是以汉字严为例,演示如何实现 UTF-8 编码。

严的 Unicode 是 4E25(100111000100101),依据上表,能够发现 4E25 处在第三行的范畴内(0000 0800 – 0000 FFFF),因而严的 UTF-8 编码须要三个字节,即格局是 1110xxxx 10xxxxxx 10xxxxxx。而后,从严的最初一个二进制位开始,顺次从后向前填入格局中的 x,多出的位补 0。这样就失去了,严的 UTF-8 编码是 11100100 10111000 10100101,转换成十六进制就是 E4B8A5。

总结
如果你感觉此文对你有一丁点帮忙,点个赞。或者能够退出我的开发交换群:1025263163 互相学习,咱们会有业余的技术答疑解惑

如果你感觉这篇文章对你有点用的话,麻烦请给咱们的开源我的项目点点 star: http://github.crmeb.net/u/defu 不胜感激!

正文完
 0