Loading

编码

参考文章:

http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html

https://mp.weixin.qq.com/s/QjU9lSekpbaF7fugZbyzkg


字节

字节(英语:Byte),通常用作计算机信息计量单位,不分数据类型。 一个字节代表八个比特(英语:Bit)。这个是最基本的概念了,计算机只能识别1和0组成的二进制位。一个数就是1位(bit),为了方便计算,我们规定8位就是一个字节。

例如 :00001111 这个8位二进制数就占了一个字节的存储容量。

字符

字符和字节不太一样,任何一个文字或符号都是一个字符,但所占字节不一定,不同的编码导致一个字符所占的内存不同。字符是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等。 也就是说,一个数字是一个字符,一个文字是一个字符,一个标点符号也是一个字符。如:1 是 字符,“汉” 是字符,“!”感叹号是字符。

字符集

charset 是 character set 的简写,即字符集。字符的集合就叫字符集。ASCII字符集就是一种字符集。

编码

编码是一个非常宽泛的概念!虽然我们一直用编码特指字符集编码,但这只是一种狭义的理解,广义的理解则有很多:

  • 文字是对声音的编码
  • 照相机,摄像机把光信号编码成图像及视频
  • 我们还经常能看到条形码二维码,这些都是编码

著名的摩尔斯电码其实也是一种编码:

在图片中,M的编码就是“━ ━”,其它类似。

字符编码 是 编码的一种情况,不过我们学计算机的说到编码就是字符编码。

字符编码

encoding 是 charset encoding 的简写,即字符集编码,简称编码。定义字符集中的字符如何编码为特定的二进制数,以便在计算机中存储(就是将字符在字符集中的对应位置化为二进制)。

字符集和字符编码一般一 一对应,Unicode字符集例外,因为Unicode字符集有三种编码方式(utf-8,utf-16,utf-32)

字符编码 和 字符集的区别

1、字符集表示一定范围的字符,如A、B定义为字符集1,A、B、C、D定义为字符集2,编码则是设置字符集中的字符在计算机中的存储方式,如字符1采用八进制编码,字符集2采用十六进制编码。

2、一个字符集可以有多中编码方式,如Unicode有utf-8,utf-16,utf-32三种编码方式。

不同的编码方式都是为了能实现准确表示字符同时存储空间小且使用简单。

 

Unicode由来

ASCII 码

上个世纪60年代,美国制定了一套字符编码,对英语字符与二进制位之间的关系,做了统一规定。这被称为 ASCII 码,一直沿用至今。

ASCII 码一共规定了128个字符的编码,比如空格SPACE是32(二进制00100000),大写的字母A是65(二进制01000001)。这128个符号(包括32个不能打印出来的控制符号),只占用了一个字节的后面7位,最前面的一位统一规定为0

 

中文编码

ASCII编码能满足英文的需求,但是不同的国家都有自己的语言与符号,ASCII肯定是不够用的,于是不同国家都制定了自己国家语言的编码,中文编码演化为:

GB2312(80年代提出,我国简体中文编码,包含7445个字符)

-->GBK(90年代提出,包含简体中文和繁体中文)

-->GB18030(00年代提出,包含简体中文、繁体中文和少数民族文及特殊符号,字符由1个或2个或4个字节组成)

 

世界编码各不相同,于是就需要统一世界编码,于是有了Unicode编码,Unicode将全世界编码都进行了统一编码,世界上所有的字符都分配了一个码值,类似每个人的身份证号,比如,U+0639表示阿拉伯字母Ain,U+0041表示英语的大写字母A,U+4E25表示汉字严

可以查询unicode.org,或者专门的汉字对应表

 

Unicode 的问题

需要注意的是,Unicode 只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。

比如,汉字严的 Unicode 是十六进制数4E25,转换成二进制数足足有15位(100111000100101),也就是说,这个符号的表示至少需要2个字节。表示其他更大的符号,可能需要3个字节或者4个字节,甚至更多。

 

这里就有两个严重的问题:

1、如何才能区别 Unicode 和 ASCII ?计算机怎么知道三个字节表示一个符号,而不是分别表示三个符号呢?

2、我们已经知道,英文字母只用一个字节表示就够了,如果 Unicode 统一规定,每个符号用三个或四个字节表示,那么每个英文字母前都必然有二到三个字节是0,这对于存储来说是极大的浪费,文本文件的大小会因此大出二三倍,这是无法接受的。

 

它们造成的结果是:

1)出现了 Unicode 的多种存储方式,也就是说有许多种不同的二进制格式,可以用来表示 Unicode。

2)Unicode 在很长一段时间内无法推广,直到互联网的出现。

 

UTF-8

互联网的普及,强烈要求出现一种统一的编码方式。UTF-8 就是在互联网上使用最广的一种 Unicode 的实现方式。其他实现方式还包括 UTF-16(字符用两个字节或四个字节表示)和 UTF-32(字符用四个字节表示),不过在互联网上基本不用。重复一遍,这里的关系是,UTF-8 是 Unicode 的实现方式之一。

 

UTF-8 最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。

 

UTF-8 的编码规则很简单,只有二条:

1)对于单字节的符号,字节的第一位设为0,后面7位为这个符号的 Unicode 码。因此对于英语字母,UTF-8 编码和 ASCII 码是相同的。

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

跟据上表,解读 UTF-8 编码非常简单。如果一个字节的第一位是0,则这个字节单独就是一个字符;如果第一位是1,则连续有多少个1,就表示当前字符占用多少个字节。

 

由于最高位不同,多字节中不会包含一字节的模式。对于 UTF-8 而言,二字节的模式也不会包含在三字节模式中,也不会在四字节中;三字节模式也不会在四字节模式中,这样就解决上面所说的搜索匹配难题。

image

可以看到,由于固定位上的 0 和 1 的差别,使得二字节既不会与三字节的前两字节相同,也不会它的后两字节相同。

这也每当进行搜索的时候,每个二字节和三字节的编码没有重叠,因为最高位不同呀~所以不会出现搜索同一个出现两个的结果。不过就是有效编码空间少了.

 

对于0x00-0x7F之间的字符,UTF-8编码与[ASCII编码]完全相同。

“汉”字的Unicode编码是0x6C49。0x6C49在0x0800-0xFFFF之间,使用3字节模板:1110xxxx 10xxxxxx 10xxxxxx。将0x6C49写成二进制是:0110 1100 0100 1001, 用这个比特流依次代替模板中的x,得到:11100110 10110001 10001001,即E6 B1 89。

 

UTF-16

Unicode取值范围目前是 U+0000 ~ U+10FFFF,理论大小为 10FFFF+1=110000(为啥+1,因为从0开始嘛~)。

全部范围可以均分成 17 个 65536 大小的部分,这里面的每一个部分就是一个平面(Plane)。编号从 0 开始,第一个平面称为 Plane 0。

 

 

第一个平面即是 BMP(Basic Multilingual Plane 基本多语言平面),也叫 Plane 0,它的码点范围是 U+0000 ~ U+FFFF。这也是我们最常用的平面,日常用到的字符绝大多数都落在这个平面内。

 

后续的 16 个平面称为 SP(Supplementary Planes)。显然,这些码点已经是超过 U+FFFF 的了,所以已经超过了 16 位空间的理论上限,对于这些平面内的字符,UTF-16 采用了四字节编码。

前面的 BMP 缩略图中有一片空白,这就是所谓的代理区(Surrogate Area)了。

 

 

从 D8~DF。其中前面的红色部分 D800–DBFF 属于高代理区(High Surrogate Area),后面的蓝色部分 DC00–DFFF 属于低代理区(Low Surrogate Area),各自的大小均为 4×256=1024。

代理区是 UTF-16 为了编码增补平面中的字符而保留的,总共有 2048 个位置,均分为高代理区(D800–DBFF)和低代理区(DC00–DFFF)两部分,各1024,这两个区组成一个二维的表格,共有1024×1024=210×210=24×216=16×65536,所以它恰好可以表示增补的 16 个平面中的所有字符。

posted @ 2021-06-16 20:33  梦醒点灯  阅读(743)  评论(0编辑  收藏  举报