前言
在计算机中,我们如何标识数字,英文字母(az/AZ),中文,特殊符号(,.?<>),等各种字符呢?
人们最终想到了对这些字符进行编码,比如在ASCII码中,用一个字节的大小(8个bit位,故可标识的数量是2^8=256个字符,但只用了128个,即(0~127))
比如: 65 代表英文字母 A, 48 代表数字 0
除此之外,还有很多非打印字符(换行符、制表符等),以及控制字符(退格、响铃等)控制编码
本文中你将了解到:
-
常见的字符编码格式
-
字节序标记: 大端方式(Big endian) / 小端方式(Little endian)
-
带BOM是什么意思
常见的字符编码格式
ASCII
-
单字节编码,使用一个字节的大小来标识一个字符(1 Byte = 8 bit, 所以克表示的数量为2^8 = 256个),到目前为止共定义了128个字符(0~127)
-
仅中文常用字符就不止256个, 因此ASCII在全世界范围肯定是不够用的,所以后来才出现了很多扩展的编码格式
-
如今的其他编码格式基本都兼容ASCII,可以理解为在它的基础上进行扩展
ANSI
-
American National Standards Institute(美国国家标准学会),由这个标准学会指定的一种编码规则
-
使用1 - 4个字节来代表一个字符
-
ANSI在不同语言系统上代表不同的编码
-
不同ANSI编码之间互不兼容
-
在简体中文windows系统中代表GBK
-
在日文windows中代表Shift_JIS
GB2312/GBK/GB18030
-
GB2312:对ANSI的简体中文扩展,共收录了7000个字符
-
GBK:国标扩展,由于GB2312支持的汉字太少而且不支持繁体中文,所以GBK对GB2312进行了扩展,以便支持繁体中文和更多的字符,共收录了大概22000个字符
-
GB18030:在GBK的基础上又增加了藏文、蒙古文、维吾尔文等主要的少数民族文字
Unicode
-
由于ANSI各国的编码不同造成交流传输不便,ISO打算废除所有的地区性编码方案,建立一个全球性的编码方案,并把所有字符都编码进去,称之为 Universal Multiple-OctetCoded Character Set,简称 UCS(ISO10646)
-
同时又有 unicode.org 这个组织也制定了自己的全球性编码 unicode, 自从 unicode2.0开始, unicode 采用了与 UCS相同的字库和字码
-
现在用的是UCS-2, 即2个字节编码,而UCS-4是为了防止将来2个字节不够用才开发的
-
Unicode只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储(使用的字节数/定长存储/变长存储).怎样存储、传输这些编码则是由UTF来实现
UTF
-
在可以使用ASCII标识的字符时使用Unicode并不高效, 因为Unicode比ASCII占用大一倍的空间,而对于ASCII来说高字节对它毫无用处.为了解决这个问题,就出现了一些中间格式的字符集,它们被称为通用转换格式,即UTF(Unicode Transformation Format).这其中就有如UTF-8这种变长编码.让最常出现的字符编码尽量的短,即可使得总的存储和传输代价小很多,这也是哈夫曼压缩编码的思想.
-
UTF-8、UTF-16、UTF-32都是Unicode的一种实现.目前使用最为广泛的就是UTF-8.这些字符集看名字差别就是后边的-8/-16/-32.意义就是处理单元的比特位数(即一次拿到8/8=1,16/8=2,32/8=4个字节进行处理)
-
UTF-8:变长编码方式.也就是用这种编码出来不同字符的长度不一定相同.比如UTF-8标识ASCII中的字符需要1个字节,表示中文需要3个字节.
-
UTF-16:变长编码方式
-
UTF-32:定长4字节编码
字节序标记
处理单元为多个字节时(一次拿到多个字节进行处理),如果不分字节顺序的话,那么就会出现解读错误。比如我们一次要处理四个字节 12 34 56 78,这四个字节是表示 0x12 34 56 78 还是表示 0x78 56 34 12?不同的解释最终表示的值也不一样。因此就有了大端方式和小端方式之分。
大端方式(Big endian)
-
高位字节存在地位地址
-
低位字节存在高位地址
小端方式(Little endian)
-
高位字节存在高位地址
-
低位字节存在低位地址
显然UTF-16和UTF-32是需要区分大小端方式的,因为它们一次处理拿到的字节数不止一个,UTF8则不需要区分大小端
带BOM(签名)
-
在有些软件中(如Visual Studio 2019),把带BOM翻译为带签名
-
我们已经介绍了字节序的大端和小端方式,但是怎么让计算机知道这段文本是大端还是小端方式呢
-
这就需要在文件开头为BOM(Byte Order Mark)的字符来表明文件是大端还是小端方式来存储
-
注意:BOM是Unicode标准建议的,因此UTF-16和UTF-32编码存储的文件需要带BOM,而GB2312尽管是双字节,但是没有BOM这个概念,GBK同样也是没有BOM
-
UTF-8 不需要区分字节序,当然也就不需要BOM.可以用BOM来表明该文件的编码方式是UTF-8,但实际上非常不建议这样做,尽管Unicode标准允许在UTF-8中使用BOM,但UTF-8带BOM,是Windows基于兼容性考虑独创的格式,Linux默认不兼容.