区别:字符集 字符编码 存储编码 Unicode UTF8 UTF16 UTF32 GB2312 GBK

基本概念

  • 字符(Character) 是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等。
  • 字符集(Character set) 是一个系统支持的所有抽象字符的集合。通常以二维表的形式存在,二维表的内容和大小是由使用者的语言而定。如ASCII,GBxxx,Unicode等。
  • 字符编码(Character encoding) 是把字符集中的字符编码为特定的二进制数,以便在计算机中存储。每个字符集中的字符都对应一个唯一的二进制编码。

字符集和字符编码一般都是成对出现的,如ASCII、IOS-8859-1、GB2312、GBK,都是即表示了字符集又表示了对应的字符编码。Unicode比较特殊,有多种字符编码(UTF-8,UTF-16等)

二进制

机器码

字符集:一种或多种语言中字符的集合,每个字符有个字符编号

字符编号:字符在字符集中的索引号

存储编码(通常说的字符编码):在计算机内存中的编码格式,由字符编号转化而来

Unicode:包含全球各种语言累计百万字符的字符集,给全球字符设定规则并排了个序

ASCII:

UTF8:变长字符编码,单字节表示ASCII码,中文一般用3字节表示

GB2312:《信息交换用汉字编码字符集》国标2312-1980,基本集共收入汉字6763个和非汉字图形字符682个。整个字符集分成94个区,每区有94个位。每个区位上只有一个字符,因此可用所在的区和位来对汉字进行编码,称为区位码。把换算成十六进制的区位码加上2020H,就得到国标码。国标码加上8080H,就得到常用的计算机机内码。

GBK:全称《汉字内码扩展规范》(GBK即“国标”、“扩展”汉语拼音的第一个字母,GBK 向下与 GB 2312 编码兼容,向上支持 ISO 10646.1国际标准

Unicode 可以使用的编码有三种:

UFT-8:一种变长的编码方案,使用 1~6 个字节来存储;
UFT-32:一种固定长度的编码方案,不管字符编号大小,始终使用 4 个字节来存储;
UTF-16:介于 UTF-8 和 UTF-32 之间,使用 2 个或者 4 个字节来存储,长度既固定又可变。

UTF 是 Unicode Transformation Format 的缩写,意思是“Unicode转换格式”,后面的数字表明至少使用多少个比特位(Bit)来存储字符。

1) UTF-8
UTF-8 的编码规则很简单:如果只有一个字节,那么最高的比特位为 0;如果有多个字节,那么第一个字节从最高位开始,连续有几个比特位的值为 1,就使用几个字节编码,剩下的字节均以 10 开头。

具体的表现形式为:

0xxxxxxx:单字节编码形式,这和 ASCII 编码完全一样,因此 UTF-8 是兼容 ASCII 的;
110xxxxx 10xxxxxx:双字节编码形式;
1110xxxx 10xxxxxx 10xxxxxx:三字节编码形式;
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx:四字节编码形式。

xxx 就用来存储 Unicode 中的字符编号。字符编号与编码之间就有了映射关系。

下面是一些字符的编码实例(绿色部分表示本来的 Unicode 编号):

字符    N    æ    ⻬
Unicode 编号(二进制)    01001110    11100110    00101110 11101100
Unicode 编号(十六进制)    4E    E6    2E EC
UTF-8 编码(二进制)    01001110    11000011 10100110    11100010 10111011 10101100
UTF-8 编码(十六进制)    4E    C3 A6    E2 BB AC
对于常用的字符,它的 Unicode 编号范围是 0 ~ FFFF,用 1~3 个字节足以存储,只有及其罕见,或者只有少数地区使用的字符才需要 4~6个字节存储。

2) UTF-32
UTF-32 是固定长度的编码,始终占用 4 个字节,足以容纳所有的 Unicode 字符,所以直接存储 Unicode 编号即可,不需要任何编码转换。浪费了空间,提高了效率。

3) UTF-16
UFT-16 比较奇葩,它使用 2 个或者 4 个字节来存储。

对于 Unicode 编号范围在 0 ~ FFFF 之间的字符,UTF-16 使用两个字节存储,并且直接存储 Unicode 编号,不用进行编码转换,这跟 UTF-32 非常类似。

对于 Unicode 编号范围在 10000~10FFFF 之间的字符,UTF-16 使用四个字节存储,具体来说就是:将字符编号的所有比特位分成两部分,较高的一些比特位用一个值介于 D800~DBFF 之间的双字节存储,较低的一些比特位(剩下的比特位)用一个值介于 DC00~DFFF 之间的双字节存储。

如果你不理解什么意思,请看下面的表格:

Unicode 编号范围
(十六进制)    具体的 Unicode 编号
(二进制)    UTF-16 编码    编码后的
字节数
0000 0000 ~ 0000 FFFF    xxxxxxxx xxxxxxxx    xxxxxxxx xxxxxxxx    2
0001 0000---0010 FFFF    yyyy yyyy yyxx xxxx xxxx    110110yy yyyyyyyy 110111xx xxxxxxxx    4

位于 D800~0xDFFF 之间的 Unicode 编码是特别为四字节的 UTF-16 编码预留的,所以不应该在这个范围内指定任何字符。如果你真的去查看 Unicode 字符集,会发现这个区间内确实没有收录任何字符。

UTF-16 要求在制定 Unicode 字符集时必须考虑到编码问题,所以真正的 Unicode 字符集也不是随意编排字符的。

总结
只有 UTF-8 兼容 ASCII,UTF-32 和 UTF-16 都不兼容 ASCII,因为它们没有单字节编码。

GB2312、GBK、Shift-JIS 等特定国家的字符集都是在 ASCII 的基础上发展起来的,它们都兼容 ASCII,所以只能采用变长的编码方案:用一个字节存储 ASCII 字符,用多个字节存储本国字符。

以 GB2312 为例,该字符集收录的字符较少,所以使用 1~2 个字节编码

对于 ASCII 字符,使用一个字节存储,并且该字节的最高位是 0;
对于中国的字符,使用两个字节存储,并且规定每个字节的最高位都是 1。

由于单字节和双字节的最高位不一样,所以很容易区分一个字符到底用了几个字节。
 

一般情况下用无BOM的形式吧,除非有问题的时候,再考虑换有BOM的。Windows系统保存的都是有BOM的,所以你可以看到,用记事本保存一个UTF-8的txt,其实是有BOM的,这一点需要注意。另外不同的文本编辑器对于有无BOM的称呼也略有不同,比如EditPlus,有BOM的称为UTF-8+,无BOM的称为UTF-8,而在Notepad++中,有BOM的被称为标准UTF-8,而无BOM则被称为UTF-8无BOM。

UTF-8编码的文本文档,有的带有BOM (Byte Order Mark, 字节序标志),即0xEF, 0xBB, 0xBF,有的没有。Windows下的txt文本编辑器在保存UTF-8格式的文本文档时会自动添加BOM到文件头。在判断这类文档时,可以根据文档的前3个字节来进行判断。然而BOM不是必需的,而且也不是推荐的。对不希望UTF-8文档带有BOM的程序会带来兼容性问题,例如Java编译器在编译带有BOM的UTF-8源文件时就会出错。而且BOM去掉了UTF-8一个期望的特性,即是在文本全部是ASCII字符时UTF-8是和ASCII一致的,即UTF-8向下兼容ASCII。

在具体判断时,如果文档不带有BOM,就无法根据BOM做出判断,而且IsTextUnicode API也无法对UTF-8编码的Unicode字符串做出判断。那在编程判断时就要根据UTF-8字符编码的规律进行判断了。

猜你喜欢

转载自blog.csdn.net/smartgps2008/article/details/88372925