常用编码学习

常用编码

在计算机世界,所有信息都是用二进制存储。每一个二进制有0和1两种状态。

所以8个二进制就可以组合成256种状态,也就是一个字节。

也就是说,一个字节可以用来表示256种不同的状态,每一个状态对应一个符号,也就是256个符号,从00000000—11111111。

ASCII码

一共规定了128个字符的编码,包含大小写字母、数字、还有空格等一些常用符号,这128个符号中有32个不能打印出来的控制符号。只占用了一个字节的后面7位,也就是最前面一位都是0.

大写字母A是65,也就是二进制的01000001。

空格是32,也就是二进制的00100000。

非ASCII编码

上面讲的ASCII编码规定的128个字符,对英语来说足够用了,但是用来表示其他语言,128个符号不够用。例如,法语字母上面有注音符号,它就无法用ASCII码表示。于是,一些欧洲国家就决定,利用字节中闲置的最高位编入新的符号。

比如,法语的é的编码为130,二进制位10000010,这样以来欧洲国家可以使用8个二进制的所有组合,也就是最多256个符号。

但是,这也有问题,130在法语编码中表示é,而在希伯来语编码中却代表字母Gimel(ג),在俄语编码中又代表另一个符号。但是不管怎样,所有这些编码方式中,0—127表示的符号是不一样的,不一样的只是128—255的这一段。

至于亚洲国家的文字,额….汉字就10W+,256种符号肯定不够,就必须使用多个字节表达一个符号。比如,简体中文常见的编码方式是GB2312,使用256个字节表示一个汉字,所以理论上最多表示256*256=65536个符号。

当然,世界上的编码方式有很多,不止上面提到的这些。

Unicode

世界上存在着多种编码方式,同一个二进制数字可以被解释不同的符号。因此,要想打开一个文本文件,就必须知道它的编码方式,否则用错误的编码方式解读,就会出现乱码。

Unicode是一种把世界上所有符号都纳入其中,每一个符号都给予了一个独一无二的编码,那么乱码问题就会消失。

Unicode是一个很大的集合,现在的规模可以容纳100多万个符号,每个符号的编码都不一样,比如:

U+0639表示阿拉伯字母Ain。

U+0041表示英语的大写字母A

U+4E25 表示汉字严

Unicode的问题

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

例如:汉字转化为二进制是100111000100101,足足有15位,也就是最少需要两个字节,甚至有更大的符号,需要3个字节或者4个字节,甚至更多。

这就有了两个严重的问题:

1.如何区分Unicode和ASCII,计算机怎么知道三个字节表示一个符号,而不是表示三个符号呢?

2.我们已经知道英文字母只用一个字节表示就足够了,如果Unicode同一规定,每个符号用三个或四个字节表示,那么每个英文字母前都必须有2—3个字节是0,这对于数据存储来说是极大的浪费,文本文件的大小因此会打出2—3倍,这是无法接受的。

UTF-8闪亮登场

UTF-8Unicode的一种实现方式,其他实现方式还有UTF-16(字符用2—4个字节表示),UTF-32(字符用四个字节表示),不过其他的在互联网上基本不用,UTF-8就是为了统一编码方式产生的,也是互联网上使用最广的一种Unicode的实现方式。

UTF-8的最大特点,就是它是一种边长的编码方式,可以使用1—4个字节来表示一个符号,根据不同的符号而变化字节长度。

它的规则很简单,只有两条:

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

对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律为10。

汉字的Unicode是4E25(100111000100101),需要用三个字节存储,根据上面的规则,即格式为:

1110xxxx 10xxxxxx 10xxxxxx

记住,二进制是从后往前存储的,读也是从后往前读的,所以我们先填充第三个字节,从二进制的后面读取,填充完后变成了:

1110xxxx 10xxxxxx 10100101

再根据同样规则填充第二个字节,填充完后变成了:

1110xxxx 10111000 10100101

最后填充最后一个字节:

1110x100 10111000 10100101

不对啊,怎么少了一个字节?没事,少了的用0补位:

11100100 10111000 10100101

Unicode与UTF-8的转换

这两种编码的转换可以通过程序实现,在Windows平台下,最简单的方法是,通过记事本另存为:

ACSI就是ACSII,是Windows英文系统的默认的编码格式,但是对于Windows简体中文版默认就是GB2312,针对繁体中文版默认就是Big5。

而现显示的Unicode都是使用UCS-2编码方式存储的Unicode字节,只不过默认是little endian格式,而另一个选项是Unicode big endian格式。

Unicode little endianUnicode big endian的转换:

简单举个例子,UCS-2格式可以存储Unicode码。汉字的Unicode码为4E25,需要用两个字节存储,一个字节是4E,另一个是25。4E在前,25在后就是Big endian(从前往后),25在前,4E在后,就是Little endian(从后往前)。

那计算机怎么知道某一个文件到底采用哪一种方式编码呢?

Unicode规范定义,每一个文件最前面分别加入一个表示编码顺序的字符,这个字符的名字叫做 “zero width no-break space” ,用FEFF表示,正好是两个字节。

如果一个文本文件的头两个字节是FE FF,表示是Big endian方式,如果头两个字节是FF FE,表示是Little endian方式。

本文大部分来自阮一峰大神的个人博客:http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html

Everything has its time and that time must be watched. If you have any question, please contact email linqtosql@qq.com.
原文地址:https://www.cnblogs.com/Fill/p/9581585.html