字符集那些事 上篇

字符集那些事 上篇

开发过程中最痛苦的事情就是字符集的问题了。稍有不注意就会出现乱码。都是编码方式惹的祸,所以ASCII、Unicode Utf8/16/32、GBK等字符集和编码方式一起来了解下。

ASCII

ASCII 码使用指定的 7 位或 8 位二进制数组合来表示 128 或 256 种可能的字符。标准ASCII码也叫基础ASCII码,使用低 7 位二进制数,剩下的最高位二进制为0,来表示所有的大写和小写字母,数字 0 到 9、标点符号,以及在美式英语中使用的特殊控制字符。

几个常见字母的ASCII码表示方式:

  • 'A'十进制为65,二进制 0110 0001;
  • 'a'十进制为97,二进制 1001 0111;
  • '0'十进制为48,二进制 0100 1000;

在美国 128 个字符足够用,但是在其它国家就不够用了,所以其它国家会将最高位利用起来,这样便可以最多表示 256 个字符。 最高位为0时为标准ASCII,当最高位为1XXXXXXX时可以表示新的字符;这样就导致一个问题,0-127表示的符号是一样的,不一样的只是128-255的这一段,如果不知道这一段的字符就会出现乱码的情况。

Unicode

ASCII的弊端就是最多只能表示256个字符,远远不够用。而且不同国家和地区的实现方式还不同,大家相互不能认识彼此,沟通变得很困难,后来国际标准化组织(ISO)制定了一套规范 Unicode 字符集。

Unicode第一个版本采用16bit,两个字节保存,用0至65535之间的数字来表示所有字符。其中0-127这128个数字表示的字符仍然跟ASCII完全一样,可以理解为0-65535中每一个数字都对应着一个字符,这个数字就是这个字符的唯一ID。

随着时间的推移65536个字符也远远不够,目前的Unicode4.0已经采用4字节来编码。虽然解决了问题,但是,英文字母的话,本来一个字母只有一个字节就够了,现在转成unicode以后,却要无端地扩大了4倍,这是一种严重的浪费。这时就出现了Utf,这是一种编码方式。

Utf

如果说Unicode/ASCII是字符的唯一标识,那么Utf编码方式就是字符标识在计算机内存中的表示方式。

Utf8

Utf8是可变长度编码方式,先来看表示方式

Unicode(16进制) Utf8(二进制)
0000 0000-0000 007F(0-127) 0xxxxxxx
0000 0080-0000 07FF(128-2047) 110x xxxx 10xx xxxx
0000 0800-0000 FFFF(2048-65535) 1110 xxxx 10xx xxxx 10xx xxxx
...... .......
  • 标准ASCII 0-127,直接使用原始字符标识。比如 'A' 为 0100 0001,使用UTF-8编码方式,就使用一个字节表示。其值就是0x41。

  • 当字符标识超过127,那么需要两字节的Utf-8来进行编码,都编码成这个样子:110x xxxx 10xx xxxx。第一字节的前三位是110,第二字节的前两位是10,比如128,它的二进制是1000 0000,那么它的UTF-8就必须是两字节的。把后面的6个0,编码到第二字节,把前面的10,编码到第一字节,那么结果就是:

编码 二进制
字符标识127 ------------10-----00 0000
Utf8编码127 1100 0010 1000 0000
  • 当字符标识超过2047,那么需要三字节的Utf-8的编码格式是这样的:1110 xxxx 10xx xxxx 10xx xxxx,可以编码16位数字,涵盖了大部分的常用汉字。

Utf16

UTF-16比较好理解,就是任何字符对应的数字都用2字节或者4字节来保存,属于可变长度字符编码。

  • 编号在 0000 0000-0000 FFFF 的字符(常用字符集),直接用两个字节表示,也就是Unicode的编码标识。
  • 编号在 0001 0000-0010 FFFF 的字符,需要用四个字节表示。
Unicode 编号范围(十六进制) UTF-16 编码 字节数
0000 0000-0000 FFFF xxxx xxxx xxxx xxxx 2
0001 0000-0010 FFFF 1101 10xx xxxx xxxx 1101 11xx xxxx xxxx 4

Utf32

Utf32中每个字符都使用4字节表示,即使是ASCII,也同样使用4字节表示,非常浪费空间,但是长度固定,不会变化。

总体来说 Utf8/16/32各有优缺点,具体如何使用需要根据场景分析。

GBK

由于 Utf 字符编码对中国来说,Utf8 实在是太冗余,一个中文字符要占用 3 个字节,存储和传输的效率不但没有提升,反而下降了。于是,国人就定义了一套编码规则:当字符标识小于127时,与ASCII的字符相同,但当两个大于127的字符连接在一起时,就代表一个汉字,第一个字节称为高字节(从0xA1-0xF7),第二个字节为低字节(从0xA1-0xFE),这样大约可以组合7000多个简体汉字。这个规则叫做GB2312。 GBK在保证不和GB2312、ASCII冲突前提下,也用每个字占据2bytes的方式又编码了许多汉字。经过GBK编码后,可以表示的汉字达到了20902个,另有984个汉语标点符号、部首等。

我们常用的编辑器中windows系统,如Notepad++中ANSI编码方式在中国一般采用GBK的编码方式,在其它国家会有变为其它的编码方式,统一称呼为ANSI。

总结

简单的说,ASCII、Unicode就是字符集,里面对每个字符都会分配一个唯一的ID,而 Utf8/16/32、GBK是字符真正在计算机中存储的内存,也就是如何表示这个ID,相当于编码格式。

以上就是常用字符集和编码方式的概念,对于我们常用的开发环境字符编码使用方式,以及不同编码方式之间的转换,请关注公众号 玄同学 看下篇《字符集那些事(下)》

参考资料

https://baike.baidu.com/item/ASCII/309296?fr=aladdin
https://blog.csdn.net/u011447369/article/details/55504678
https://blog.csdn.net/longwen_zhi/article/details/79704687
https://blog.csdn.net/benben683280/article/details/78919206?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-5.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-5.control

posted @ 2020-12-20 15:59  超超加油  阅读(169)  评论(0)    收藏  举报