内容简介:花括号MC(huakuohao-mc):关注JAVA基础编程及大数据,注重经验分享及个人成长。
花括号MC(huakuohao-mc):关注 JAVA 基础编程及大数据,注重经验分享及个人成长。
在谍战剧里,我们经常看到这样一个桥段,特工人员,千辛万苦拿到一条信息,打开一看是一串数字,然后赶紧跑到一个秘密地方,拿出一个密码本(也可能是一本唐诗选),按照一定规则(只有自己人知道),比如第一个数字表示页数,第二个数字表示行数,第三个数字表示第几个字,逐一将信息翻译出来。如果这个过程中用了错误的密码本,或者不知道规则,那么将会解码失败。
计算机的编解码过程跟上面的过程是一样一样的。
计算机只认 0
和 1
,所有的影像和字符最终都会转换成计算机能够认识的二进制。一个二进制位(bit)可以表示两种状态 0
和 1
,一个字节(byte)由八个二进制位组成,所以一个字节一共可以表示256( 2^8
)种状态。如果我们规定每种状态代表一个字符,那么一个字节就可以表达出 256
个字符。
ASCII
计算机是由美国人发明的,所以在最初设计编码的时候,就只考虑了英文的编码。英文字符很少,加上一些特殊字符,一共也就100个左右,确切的说是128个。这样的话用一个字节进行编码就完全够了,不仅够用了,而且还富裕出一位,即第一位一直没有参与编码,统一定为 0
。这就是所谓的 ASCII
编码。在 ASCII
编码中,空格 SPACE
是 32
(二进制 00100000
),大写的字母 A
是 65
(二进制 01000001
)。
非ASCII
随着计算机的普及,欧洲也开始普及计算机,欧洲人发现 ASCII
规定的 128
个字符不能满足他们的使用,比如,在法语中,字母上方有注音符号,就无法用 ASCII
码表示。于是,一些欧洲国家就决定,把字节中闲置的第一位编入新的符号。比如,法语中的 é
的编码为 130
(二进制 10000010
)。这样一来,这些欧洲国家使用的编码体系,最多可以表示 256
个符号。这就是大家经常见到的 ISO-8859-1
编码,也叫 Latin1
编码。
中文编码
随着计算机的普及,国人也开始使用计算机,但是发现按照之前的编码方式,根本就没有汉字什么事儿,也就是计算机根本没办法认识汉字。
GB2312
为了能够让计算机认识汉字,我们决定对汉字进行编码,本着敢想敢干的精神,我们规定用两个字节表示一个汉字。
具体规则是这样的:一个小于 127
的字节代表的意义与原来的 ASCII
相同,但两个大于 127
的字节连在一起时,就表示这是一个汉字,前面的一个字节称为高字节,后面一个字节称为低字节,这样我们就可以组合出 6763
个简体汉字。这就是大家常说的 GB2312
编码。
GBK
很显然 GB2312
编码的 6763
个汉字,并不能适应所有的使用场景,比如“喆”字就不再其中,于是在 GB2312
的基础上又进行了新的扩展,规定只要第一个字节是大于 127
的就OK,至于第二个字节是大于 127
还是小于 127
都无所谓了。经过这样的改动之后,收录的汉字及符号就可以达到 2W
多个,这就是我们常说的 GBK
编码。
再后来,人们继续对第二个字节进行扩展,发展出了 GB18030
编码,比 GBK
又多出了一些字符编码。
至此,所有的汉字编码都是用两个字节表示的,但是英文是用一个字节表示。上了一些年纪的 程序员 都体验过,一个汉字算两个英文字符的经历。
BIG-5
上面提到的都是简体中文编码,虽然 GBK
及 GB18030
包含了部分繁体字,但是也不全面,于是台湾同胞就发了专门支持繁体字的 Big5
编码,也就是大家经常说的大五码。
一个小问题
不知道大家有没有注意到一个问题,在单字节编码的时候,对于那些大于 127
小于 256
的编码,在不同的国家代表的字母很可能不一样。比如, 130
在法语编码中代表了 é
,在希伯来语编码中却代表了字母 Gimel (ג)
,在俄语编码中又会代表另一个符号。在汉字的双字节编码中也存在这样的问题,比如 BIG5
编码跟 GBK
编码都是双字节编码,但是代表的汉字却不一样。
这就相当于,同样一串二进制数值,A特工组织按照他们的规则解析出来可能是“你好”,而B特工组织按照他们的规则解析出来可能是“滚蛋”。特工组织之间的翻译标准不一样是相当有必要的,但是计算机的编码规则如果各不相同就比较麻烦了。比如你跟台湾的志玲姐姐聊天,志玲姐姐用 BIG5
编码给你发了一封信,然后你用 GBK
去解码,……,也许就没有然后了。
Unicode
为了解决上面的问题,有个叫 ISO
的国际标准组织,决定放弃所有区域性编码,如 BIG5
, GBK
等,重新制定一个新的编码,这个编码集将包含所有字符的编码,这样大家就都统一了,这套编码的英文全称“Universal Multiple-Octet Coded Character Set”,简称UCS, 俗称 “Unicode“。 Unicode
的出现相当于秦始皇对度量衡跟货币进行了统一。
Unicdoe
按照日常字符的使用频繁度划分了 17
个平面,编号为 0-16
, 0
号平面称为基本多语言平面(Basic Multilingual Plane,简称 BMP
),包含了日常使用最频繁的字符,编码范围从 0000
到 FFFF
,这样该平面可以表示 2^16=65536
个字符;其它平面的编码范围也是从 0000
到 FFFF
,所以其它平面也可以编码 65535
个字符,这样 17
个平面一共可以编码 17×65,536 = 1,114,112
个符号。
我们最常用的 Unicode
编码使用的是多语言平面的编码,即所有字符都用两个字节进行编码(其它平面可能需要三个或四个字节)。举个例子比如中国的'中'字 Unicode
码是 4E2D
,小写'a'的 Unicode
码是 0061
.
这里面存在两个问题,如果所有英文字符都是按照 Unicode
编码,那么会出现浪费存储空间的问题。明明一个字节可以搞定的事情,偏偏要用两个字节。
第二个问题就是计算机如何知道这是 Unicode
编码还是 ASCII
编码,也就是 2
个字节表示的一个字符,还是 2
个字符呢。
UTF
UTF
的全称是 Unicode Transformation Format
,也就是 Unicode
的转换格式。上面提到了,如果直接使用 Unicode
码进行存储会存在浪费空间的问题,而 UTF-8
的出现就是为了解决该问题, UTF-8
使用变长的方式存储 Unicode
码,也就是英文字符继续使用一个字节进行存储,但是汉字要使用 3
个字节。那么 UTF-8
是如何做到的呢。
首先,对于单字节的符号,字节的第一位设为 0
,后面 7
位为这个符号的 Unicode
码。因此对于英语字母, UTF-8
编码和 ASCII
码是相同的。
其次,对于 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 |
根据上表,对 UTF-8
编码进行解读会发现,如果一个字节的第一位是 0
,则这个字节单独就是一个字符;如果第一位是 1
,则连续有多少个 1
,就表示当前字符占用多少个字节。
举个例子
假设“hello世界”这样一个字符串,他们的 Unicode
的编码分别是
1h--0068 2e--0065 3l--006C 4l--006C 5o--006F 6世--4E16 7界--754C
按照 UTF-8
的编码规则可以得到如下 UTF-8
编码
1h--01101000 2e--01100101 3l--01101100 4l--01101100 5o--01101111 6世--11100100-10111000-10010110 7界--11100111-10010101-10001100
可以看到用 UTF-8
编码之后,英文字符占用一个字节,而汉字占用了三个字节,一共需要 11
个字节,而如果直接存储 Unicode
码则需要 14
个字节。 UTF-8
编码对于英文来说节省了很大空间,但是对于中文来说增加了空间。
Little endian 和 Big endian
上面提到 Unicode
是用两个字节表示字符,如果第一个字节在前,就是"大端方式"(Big endian),第二个字节在前就是"小端方式"(Little endian)。'世'字的 Unicode
码是 4E16
,一个字节是 4E
,一个字节是 16
, 存储的时候如果 4E
在前就是大端存储,如果是 16
在前就是小端存储。
那么计算机是怎么知道一个文件是采用哪种编码方式呢?
Unicode
规范定义,每一个文件的最前面分别加入一个表示编码顺序的字符,这个字符的名字叫做"零宽度非换行空格"(zero width no-break space),用 FEFF
表示。这正好是两个字节,而且 FF
比 FE
大 1
。
如果一个文本文件的头两个字节是 FE FF
,就表示该文件采用大头方式;如果头两个字节是 FF FE
,就表示该文件采用小头方式。
总结
UTF-8
编码是基于 Unicode
字符集的一种编码实现。现在几乎所有的编程语言和操作系统都支持 Unicode
编码,使用 Unicode
编码之后,再也不会出现上文提到的一个汉字等于两个英文字符的尴尬局面。
GBK
, BIG5
等都属于区域性编码只能在固定范围内使用,比如 GBK
只适合在简体中文环境使用,虽然 GBK
相比于 UTF-8
更节省空间,但现在全世界都变成地球村了,所以还是建议大家都使用 UTF-8
编码。
ANSI
:在 window
下,如果我们用记事本打开文档,经常会见到 ANSI
编码方式,这是 Windows
默认的编码方式。对于英文文档采用 ASCII
编码,对于简体中文文档采用 GB2312
编码(只针对 Windows
简体中文版,如果是繁体中文版会采用 Big5
码)。
·END·
花括号MC
Java·大数据·个人成长
微信号:huakuohao-mc
点一下你会更好看耶
以上所述就是小编给大家介绍的《作为一个程序员,你应该知道的编码知识》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- [译] 值得程序员反复品味的编码智慧
- [译] 值得程序员反复品味的编码智慧
- 作为一个程序员,你应该知道的编码知识
- 编码人员,程序员,开发人员和软件工程师之间的差异
- 编码、摘要和加密(一)——字节编码
- 新媒体编码时代的技术:编码与传输
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
ASP.NET 2.0入门经典
哈特 / 清华大学出版社 / 2006-8 / 78.00元
该书是Wrox红皮书中的畅销品种, 从初版、1.0版、1.1版到目前的2.0版,已经3次升级,不仅内容更加完善、实用,还展现了.NET 2.0的最新技术和ASP.NET 2.0最新编程知识,是各种初学者学习ASP.NET的优秀教程,也是Web开发人员了解ASP.NET 2.0新技术的优秀参考书。该书与《ASP.NET 2.0高级编程(第4版)》及其早期版本,曾影响到无数中国Web程序员。一起来看看 《ASP.NET 2.0入门经典》 这本书的介绍吧!