编码是计算机的基础和核心,正式因为它的存在,才能使人类语言得以保存在计算机上,信息才能够通过计算机共享。
那么,编码是怎么一回事呢?
字符集
所谓字符集,就是给所有字符的编码组成总和。早期末的美国人给所有的英文字母、常见标点符号、数字进行了编号,他们认为字符最多一百多个,只要一个字节即可表达所有的字符——这就是ASCII字符集。
1.ASCII字符集
前面已经提到,这是美国人搞出来的一套字符集,是为了美国人使用方便的字符集,它只对英文字母、常见标点符号、数字进行了编号,只用到一个字节(8位,最前面一位为0,可描述128个符号)。
2.非ASCII字符集
所谓非ASCII字符集,就是其他欧洲国家,比如法国,他们的字符比如é用传统的ASCII字符集无法表示,于是他们启用了ASCII闲置的第一位,这样一来,这样的编码体系就可以表示256个字符了。
3.Unicode字符集
不管是ASCII字符集或则是扩展的非ASCII字符集,欧美国家使用起来是很爽了,可是咱们亚洲国家使用的文字并不能被这两种方式很好的编码,于是就出现了很多更大支持更多字符的编码方式。但是这样同时也带来了一个问题:使用错误的编码方式解读文件会造成乱码。
于是,Unicode出现了。它将世界上所有的字符都囊括其中,每一个符号都有独一无二的编码,现在的规模可以容纳100+万字符。
文件存储存在的问题
有了Unicode字符集,我们可以用它表达世界上的所有字符,但是字符集只规定了单个字符的编码方式,并没有规定字符的存储方式。
比如,中文“严”的编码是4E25,转化为二进制有15位需要两个字节,而还有更多比它更大的字符需要三个、四个乃至更多的字节,当我们把这些字符存入计算机的时候,计算机怎么能知道这串二进制代表的是一个字符还是多个字符呢?
可以轻易想到的解决办法是:让Unicode统一规定4个字节为一个字符,这样就解决上面提到的字符识别的问题,事实上UTF-32就是这样干的,但是所有的英文字符只需要一个字节即可表示,这样编码的话会造成英文字符的前三个字节的所有位都是0,而这些0对于字符是没有意义的,这样的编码方式还会使文件比原来大两大三倍,这在性能上显然是无法接受的。
UTF-8
UTF-8是互联网上使用最广泛的一种Unicode实现方式。
UTF-9最大的特点是使用变长的编码方式。它可以使用1-4个字节表示一个字符,根据不同的符号变化字符的字节长度。
UTF-8的编码规则:
1).对于单字节字符,它规定这个字节的第一位为0,后7位为ASCII编码。所以对于英文字符而言,ASCII编码和Unicode编码是一样的。
2).对于n(n>1)字节的字符,它规定第一个字节的前n位都为1,n+1位为0,后面的字节前两位都为10,其他没提到的位用来存储Unicode编码。
下表总结了编码规则,字母x表示可用编码的位。
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
所以结论是:当字节大于1,UTF-8编码方式会有5-11为用于描述字节长度。
计算机怎么知道某一个文件到底采用哪一种方式编码?
Unicode规范中定义,每一个文件的最前面分别加入一个表示编码顺序的字符,这个字符的名字叫做"零宽度非换行空格"(ZERO WIDTH NO-BREAK SPACE),用FEFF表示。这正好是两个字节,而且FF比FE大1。
本文参考博客:https://blog.csdn.net/xiaolei1021/article/details/52093706