字符编码

字符编码是人类和计算机交流的桥梁

计算机只认识二进制字符(0和1),这是计算机的设计所决定的。而人类的语言字符要想在计算机中传输的话就必须转换为二进制字符。早期的计算机也只是用来处理数字,把现实中的十进制数字转换为计算机的二进制字符进行处理。随着需求的需要,计算机必须能够支持文本、音频、视频等形式的信息。所以,就必须把这些文本、音频、视频转换为二进制数字来交给计算机处理。需要一个统一的规范来把这些信息转换为二进制字符。于是就有了ASCII码、Unicode码等规范。

ASCII码

早期的计算机主要在美国流行,为了解决统一规范的问题,美国有关的标准化组织就出台了ASCII编码,统一规定了常用符号用哪些二进制数来表示。

ASCII码一共规定了128个字符(0-127号)的编码,包括32个控制字符和96个打印字符。
96个打印字符包括52个英文字母(大小写)、10个阿拉伯数字以及一些标点符号等字符

这128个符号,只占用了一个字节的后面7位,最前面的一位统一规定为0

一个字节有八位,每一位有0和1两种状态。所以一个字节有256种状态

ASCII码如下

ASCII.jpg

由上表可知:大写的字母A是65(二进制01000001)

unicode码

随着国际互联网的迅速发展,进行数据交换的需求越来越大,于是就出现了各种各样的编码体系,而不同的编码体系之间并不兼容,成为信息交换的障碍。

一些表音文字系统的语言把ASCII码进行了拓展,将闲置的高位利用起来。128-255号字符,不同的国家有不同的编码体系,无法统一
对于汉语这种表意文字系统,那就完全不够用。开玩笑,256个位置全让出来都不够我做两句诗。于是就有了GB2312、GBK等这些编码

为了包罗所有语言字符,unicode码应运而生。它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。因此,unicode码简称为UCS,又被称为统一码、万国码、单一码。

unicode(UCS)分为两种格式:UCS-2和UCS-4。顾名思义,UCS-2就是用两个字节编码(有2^16 = 65536个码位,支持大部分常用的汉字),UCS-4就是用4个字节(实际上只用了31位,最高位必须为0。有2^31 = 2147483648个码位)编码。

任何文字在Unicode中都对应一个代码点(code point),以十六进制表示,代码点格式如下

U+xxxx //U+为unicode的标志,xxxx是十六进制数
U+9ad8(程序里写做\u9ad8)代表汉字的'高'

UCS-2 取值范围为U+0000~U+FFFF
UCS-4 取值范围为U+00000000~U+7FFFFFFF
UCS-4 中 U+00000000~U+0000FFFF和UCS-2是一样的

USC-2所代表的字符以及十进制表示

UCS-2码点范围(十六进制) 十进制 说明
U+0000 - U+007F 0-127 ASCII码包含的字符
U+0080 - U+00FF 128-255 ASCII码扩展部分包含的字符
U+4E00 - U+9FA5 19968-40895 CJK(中日韩)统一表意符号

点这里查看unicode码表

在线进制转换工具

由于Unicode码只是字符集,规定了语言字符和二进制字符之间的对应关系。但没有规定字符对应的二进制码如何存储。而一个字符可能需要几个字节来表示(比如'汉这个字符',它的 Unicode 码点是 0x6c49,对应的二进制数是 110110001001001,二进制数有 15 位,需要2个字节来表示)。这就导致了一些问题,计算机怎么知道你这2个字节表示的是一个字符,而不是分别表示两个字符呢?

一种解决方案是将所有的字符都用4个字节(4字节能表示世界上绝大多数的字符)来表示,不够的就往前面补0(这种方案叫做UTF-32编码,是定长的编码)。这样确实可以解决编码问题,但是却造成了空间的极大浪费,如果是一个英文文档,那文件大小就大出了3倍,这显然是无法接受的。

于是,为了较好的解决Unicode的编码问题, UTF-8 和 UTF-16 两种当前比较流行的编码方式诞生了。

UTF-8编码

UTF是Unicode Transformation Format的缩写,可以翻译成Unicode字符集转换格式,即怎样将Unicode定义的数字转换成程序数据。

UTF-8 是目前互联网上使用最广泛的一种 Unicode 编码方式,它的最大特点就是可变长。它可以使用 1 - 4 个字节表示一个字符,根据字符的不同变换长度。

UTF-8中的8指的是字符以8位序列来编码的。用一个或几个字节来表示一个字符。这种方式的最大好处是UTF-8保留了ASCII字符的编码做为它的一部分(0x00-0x7F之间的字符),即UTF-8编码兼容ASCII编码。

UTF-8编码方式只有两条规则

//单字节
对于单个字节的字符,第一位设为 0,后面的 7 位对应这个字符的 Unicode 码点。因此,对于英文中的 0 - 127 号字符,与 ASCII 码完全相同。这意味着 ASCII 码那个年代的文档用 UTF-8 编码打开完全没有问题。

//多字节
对于需要使用 N 个字节来表示的字符(N > 1),第一个字节的前 N 位都设为 1,第 N + 1 位设为0,剩余的 N - 1 个字节的前两位都设为 10,剩下的二进制位则使用这个字符的 Unicode 码点来填充。

图表表示如下

UCS-2编码(十六进制) UCS-4编码((十六进制) UTF-8编码(二进制)
0000-007F 000000-00007F 0xxxxxxx
0080-07FF 000080-0007FF 110xxxxx 10xxxxxx
0800-FFFF 000800-00FFFF 1110xxxx 10xxxxxx 10xxxxxx
010000-10FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

01代表的位置是UTF8的元数据,x代表的位置才是Unicode的数据

从上表可以看出,4字节模板有21个x,即可以容纳21位二进制数字。Unicode的最大码位0x10FFFF也只有21位。

语言字符转换为UTF-8编码

以汉字字符为例

字的unicode编码是U+9ad8(unicode码表),对应的二进制为1001101011011000(在线进制转换工具

根据上表可知9ad8在0800-FFFF之间,使用3字节模板:1110xxxx 10xxxxxx 10xxxxxx。将字的二进制码依次填入3字节模板的x中,得到字的UTF-8编码为 111010011010101110011000,对应的十六进制为e9ab98。

所以,字对应的unicode码为9ad8(二进制1001101011011000);对应的UTF-8编码为e9ab98(二进制为111010011010101110011000)

UTF-8编码转换为语言字符

从第一个byte开始读,数第一个0出现之前的1,有几个1就代表前面几个byte是一组的,0个1就代表当前的这个byte孤家寡人一个。然后跳过这个组的所有byte,继续之前数1的环节。分好组后,按组找到上表右边的规则,把规则内x的位置保留下来,01的位置全部扔掉(01代表的位置是UTF8的元数据,x代表的位置才是Unicode的数据),拼成新的二进制串,这个串就是Unicode了。

以UTF-8编码:11100101 10001100 10111010 11100101 10011101 10010111 11101001 10010011 10111110 为例

以上有9个byte,我们从第一个byte11100101开始,数第一个0前面的1的数量,有3个1,代表3个byte是一组的。然后我们跳过这3个,第四个byte是11100101,继续数1得出有3个1,然后又给这3个byte分组。跳过这三个,到了第7个byte11101001,继续数1得出有3个1,然后又给这3个byte分组。现在我们分好组了,有3个组,分别是

[11100101 10001100 10111010], [11100101 10011101 10010111], [11101001 10010011 10111110]

现在我们按组找到表右对应的行,三组对应3字节模板,我们把行内x对应的位置保留,10的位置删除,得到新的数组

[0101, 001100, 111010], [0101, 011101, 010111], [1001,010011,111110]

然后把组内的二进制串起来得到Unicode

[0101001100111010], [0101011101010111], [1001010011111110]

转换为十六进制为533a、5757、94fe(在线进制转换工具

查询unicode码表可知,对应的字符为区块链

总结

字符集:为每一个「字符」分配一个唯一的码点(Code Point)
编码规则:将「码点」转换为字节序列的规则(编码/解码 可以理解为 加密/解密 的过程)

字符集和字符编码的出现都是为了人类的语言字符与计算机的二进制字符匹配问题。

计算机只认识二进制字符(0和1),这是计算机的设计所决定的。而人类的语言字符要想在计算机中传输的话就必须转换为二进制字符。

早期的时候字符集和字符编码没有严格的区分,像ASCII码,基本上都是将字符集里的字符进行编号(字符编号转化为二进制数后只占用一个字节),然后该字符编号就是字符的编码。所以ASCII字符集与ASCII编码其实是一回事。

而后来需要用到若干个字节,字符集和字符编码不能表示同样的意思了。比如unicode字符集(也叫unicode码、UCS)和UTF-8字符编码

ASCII码出现时间早,只需要一个字节,适用于匹配英文字符。unicode码需要若干个字节,适用于匹配世界上任何语言的字符。

unicode又称为UCS,以十六进制表示。分为两种格式:UCS-2和UCS-4。目前主要使用UCS-2

格式如下

U+xxxx //U+为unicode的标志,xxxx是十六进制数
U+9ad8(程序里写做\u9ad8)代表汉字的'高'

UCS-2 取值范围为U+0000~U+FFFF
UCS-4 取值范围为U+00000000~U+7FFFFFFF
UCS-4 中 U+00000000~U+0000FFFF和UCS-2是一样的

这里是 unicode码表在线进制转换工具

为了区分多字节表示的unicode字符到底是表示一个多字节的字符,还是多个一字节的字符,出现了UTF-8、UTF-16、UTF-32等编码方式(ASCII码就没有这个问题,因为它只需要一个字节)。普及最好的是UTF-8编码方式。UTF-8编码兼容ASCII码

unicode码与UTF-8转换规则如下

UCS-2编码(十六进制) UCS-4编码((十六进制) UTF-8编码(二进制)
0000-007F 000000-00007F 0xxxxxxx
0080-07FF 000080-0007FF 110xxxxx 10xxxxxx
0800-FFFF 000800-00FFFF 1110xxxx 10xxxxxx 10xxxxxx
010000-10FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
//单字节
对于单个字节的字符,第一位设为 0,后面的 7 位对应这个字符的 Unicode 码点。因此,对于英文中的 0 - 127 号字符,与 ASCII 码完全相同。这意味着 ASCII 码那个年代的文档用 UTF-8 编码打开完全没有问题。

//多字节
对于需要使用 N 个字节来表示的字符(N > 1),第一个字节的前 N 位都设为 1,第 N + 1 位设为0,剩余的 N - 1 个字节的前两位都设为 10,剩下的二进制位则使用这个字符的 Unicode 码点来填充。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,463评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,868评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,213评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,666评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,759评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,725评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,716评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,484评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,928评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,233评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,393评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,073评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,718评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,308评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,538评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,338评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,260评论 2 352

推荐阅读更多精彩内容