计算机编号怎么学,编码学习

数据的存储

数据都是以二进制的形式存进电脑的,比如现在一个“黄”字,不可能是在磁盘上原模原样的刻了一个“黄”,而是按照某种规则,把它转成某个二进制,然后再滴答滴答的刻录进去。这个转化规则,就是字符编码。

字符集

字符集

如果学过计算机,都应该知道有一个ASCII码表,我们可以在ASCII码表上找到任意一个英文字母或者数字对应的编码数字,比如对于“a”而言,他的编码数字就是97,这个可以根据一个字符找到对应的编码数字的表就叫做字符集,除了ASCII码这个字符集以外,还有其他各种各样的字符集,比如欧洲的ISO-8859-1,中国的GBK,还有最重要的全球通用的Unicode。

Unicode

ASCII码这个字符集太小了,只有128个字符,仅仅适用于美英等一系列英语为母语的国家,别说我们博大精深的汉文化国家了,就连欧洲的法国等国家都没法用了,因为他有些字符在ASCII码表上也是找不到的,那怎么办呢?一个字节8位可以表示256个字符,但是ASCII码只用了其中的一半,欧洲人民本着物尽其用的原则,把剩下的128个字符也充分用了起来,创建了ISO-8859-1。但是各国对剩下的128个字符的使用真是百花齐放,比如同一个编码数字,对法国可能是一个字符,但是对俄国可能又是另外一个字符,如果使用的字符集不一样,就会出现乱码。为了打击这种乱象,同时因为照顾亚洲各国人民的需要。20世纪80年代末,世界各国一起组织成了Unicode组织,他们编造了Unicode字符集,这个字符集囊括了世界上各个国家的语言和文字,使世界各国都可以对照这个字符集来编码,而不用担心乱码问题。

Unicode的编码空间从U+0000到U+10FFFF,共有1,112,064个码位可以用来映射字符;Unicode的编码空间可划分为17个平面,每个平面包括65,536(即2^16) 个码位。17个平面的码位可表示为U+xx0000到U+xxFFFF,其中xx表示平面,从0x00到0x10。第一个平面称为基本多语言平面,其它平面称为辅助平面.基本多语言平面内的U+D800到U+DFFF之间的码位是永久保留的,不会映射到任何Unicode字符。我们所使用的字符大部分都是在第一个平面。

编码方式

UTF-32

编码方式就是把字符对应的编码数字按照某种特定的规则转成字节,然后存放到计算机中。以Unicode为例,你可能会问Unicode的编码空间(编码数字)为U+0000到U+10FFFF,就按这个存放到计算机中不就OK了吗?比如“a”的编码数字为0x61,那就存为一个字节;“黄”的编码数字为0x9EC4,那就存为两个字节;“𠮷”(不是吉祥的吉,上面是个土)的编码数字为0x20BB7,那就存为三个字节。但是这里有一个问题,因为存下来的字符都是字节流串,计算机并不知道哪几个字节可以读成一个字符;比如计算机检测到00000110,你可以认为他是“a”,但实际上他是和后面的一个字节组成一个字符的。你可能又会问,那我们规定几个字节为一个字符不就OK了吗?编码空间最大为10FFFF有三个字节,那我们就规定三个字节为一个字符;比如“a”不是一个字节么,那我们在他前面补上两个都是0的字节,“黄”是两个字节,那我们就在前面补上一个0的字节,计算机读取的时候按照三个字节读取就OK了。实际上也有一种编码方式跟此类似,那就是UTF-32,只不过UTF-32是四个字节为一个字符的。这种按照规定几个字节为一个字符的编码方式有一个比较严重的问题,就是我们目前使用的文字,大部分都是Unicode第一个平面(U+0000 -U+FFFF),只需要两个字节的字符,如果是英语文章,大部分都是ASCII码,可能只需要一个字节,这样子在前面不断的补充0,会造成很大的浪费。比如我用英语写了一篇10000个字符的文章,如果纯粹用ASCII码存储的话,可能只需要10000个字节,但是用UTF-32存储的话,就需要10000 * 4个字节,整整浪费了三倍的空间。这对于勤俭节约的中国人民是多大的伤害。

UTF-16

UTF-16也是Unicode字符集的一种编码方式,它的编码规则也很简单:基本平面的字符占用 2 个字节,辅助平面的字符占用 4 个字节。那跟我们说到的一个问题很像,计算机怎么检测两个字节是属于基本平面的一个字符还是属于辅助平面的半个字符呢?这就要说到基本平面的一个特点了,在基本平面中,从 U+D800 到 U+DFFF 是一个空段,也就是说这个范围内的编码数字是没有对应的Unicode字符集的。我们可以根据这个特点,当计算机检测到某两个字节的范围在U+D800 到 U+DFFF ,就知道它是辅助平面的字符,需要跟后面两个字节一起连读。那一个辅助平面的编码数字(大于U+FFFF)要怎么转换为UTF-16呢?我们来看一个例子:

首先给出计算公式:

H = Math.floor((c-0x10000) / 0x400)+0xD800

L = (c - 0x10000) % 0x400 + 0xDC00

选项

结果

字符

𠮷(不是吉祥的吉)

编码数字(十六进制)

0x20BB7

二进制

100000101110110111

c - 0x10000

0x10BB7

二进制

10000101110110111

转成二十位二进制

0001000010 1110110111

0xD800 0xDC00

1101100000000000 1101110000000000

上下相加

1101100001000010 1101111110110111

十六进制

D842 DFB7

这就是一个编码数字转成十六进制的完整过程,我们可以到 这里 查看是否正确。UTF-16应用还算广泛,比如我们的Java的char数据类型都是用UTF-16来存储的。UTF-16的好处是基本上只需要两个字节就可以来表示一个字符了,但是坏处是对于英语的保存还是有点浪费,所以就出现了UTF-8。

730bea21040c

UTF-8

用UTF-8的编码方式,我们可以实现ASCII码字符都是一个字节的存储。那它是怎么做到的呢?

UTF-8 的编码规则有两条:

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

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

730bea21040c

我们还是以“吉”,它的编码数字为 0x20BB7,所以在 0001 0000-0010 FFFF之间,即它的UTF-8编码方式为11110xxx 10xxxxxx 10xxxxxx 10xxxxxx,我们把二进制 100000 101110 110111从最低位填到最高位,没有被填到的补0,得11110000 10100000 10101110 10110111,转成十六进制f0a0aeb7,刚好对应上图。

乱码问题

一切的乱码问题皆是因为写和读的编码方式不一致。比如你用UTF-8包括的文件,但是读的时候却用GBK,连字符集都不一致,你还指望可以正常显示吗?或者你用UTF-8保存的文件,但是用UTF-16读取文件,也会出现乱码问题。所以为了保证不乱码,必须读和写用的是同一种编码方式。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值