ASCII Unicode UTF-8 字符集 字符编码

基本概念

字符集为每个字符分配了一个唯一的编号,通过这个编号就能找到对应的字符。在编码过程中我们经常会使用字符,而使用字符的前提就是把字符放入内存中,而放入内存中的仅仅是字符的编号,而不是真正的字符实体。
这就引出一个问题,如何将这些字符编号存入内存中,还能让计算机通过这些编号找到对应的真实字符实体。

字符

字符(Character),简单点说,就是在在计算机和电信技术中各种文字和符号的总称。一个字符可以是一个中文汉字、一个英文字母、一个阿拉伯数字、一个标点符号、一个图形符号或者控制符号等。

字符集

字符集(Character Set),就是多个字符的集合。不同的字符集包含的字符数量是不一样的,包含的字符也不一样,对应的编码方式也不同。例如,GB2312 是中国国家标准的简体中文字符集(其中包含简化汉字6763个+一般符号+序号+数字+拉丁字母+日文假名+希腊字母+俄语字母+汉语拼音符号+汉语注音字母,共7445个字符),而 ASCII 字符集只包含了128个字符(其中主要字符是英文字母+拉丁字母和一些简单的控制字符)。
另外,还有其他常用的字符集,如 GBK 字符集、Unicode 字符集等。

字符编码

字符编码(Character Encoding),是指一种映射规则,根据这个映射规则可以将某个字符映射成其他形式的数据以便在计算机中存储和传输。例如 ASCII 字符编码规定使用单字节中低7位比特去编码所有字符,在这个编码规则下字母 A 的编号是 65(ASCII码),因此写入存储设备的二进制值是 01000001 。每种字符集都有自己的字符编码规则,常用的字符集编码规则还有 UTF-8 等。

字符集和字符编码

ASCII 字符集

上个世纪60年代,美国制定了一套字符编码规则,对英文字符和二进制位之间的关系做了统一规定,这套编码规则就是 ASCII 编码,一直沿用至今。
ASCII 编码一共规定了128个字符的编码规则,这128个字符形成的集合就叫做 ASCII 字符集。在 ASCII 编码中,每个字符占用一个字节的后面7位,最前面的一位规定为0。下图是 ASCII 字符集中字符和码值的对应关系:

ASCII字符集
英语用128个符号编码就够了,但是用来表示其他语言,128个符号是不够的。而且,欧洲小国家特别多,每个国家可能都有自己的语言体系,语言环境十分复杂,为了解决这个问题,这些欧洲国家使用了一套延伸的 ASCII 字符集,利用字节中闲置的最高位编入新的符号,称为 EASCIIExtended ASCII):在 EASCII 中表示的256个字符中,前128字符和 ASCII 编码表示的字符完全一样,后128个字符每个国家或地区都有自己的编码标准。例如:130(二进制为 10000010)在法语编码中代表了 é,在希伯来语编码中代表了字母 Gimel (ג),在俄语编码中又会代表另外一个字符。
根据这个规则,就形成了很多子标准:ISO-8859-1ISO-8859-2 等。这些子标准适用于欧洲不同的国家地区。

至于亚洲国家的文字和符号那就更多了,光汉字就多达10万左右,如果按照 ASCII 码单字节表示,即使用上了最高位也只能表示256种字符,肯定是不够的,所以必须使用多字节来表示一个字符,因此就出现了后面的 Unicode 字符集和 GB2312 等字符集。比如,GB2312 字符集,使用两个字节表示一个汉字,所有理论上最多可以表示 65536 个字符(2^16)。

Unicode 字符集

ASCII 码字符集总共才能容纳256个字符,对于全世界各国语言来说,很难全部包含在内,所有就出现了 Unicode 字符集。

Unicode字符集是一个很大的字符集合,现在的规模可以容纳100多万个符号,每个符号的编码都不一样。

需要注意的是,Unicode 只是一个字符集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何编码如何存储。这就造成了两个问题:

  • 如何才能区分 UnicodeASCII ?计算机如何知道三个字节表示一个字符而不是分别表示三个字符呢?
  • 已经知道英文只用一个字节表示就够了,如果统一采用 Unicode 规定,每个字符都要用三个字节来表示,那么每个英文字符前都必须有两个字节是0,这对应存储来说是极大的浪费。

因此就出现了 UTFUnicode Transformation Formats)系列的编码规则。UTF编码规则具体规定了 Unicode 字符集中的字符是如何编码的。

总结:Unicode 是一个很大的字符集,它只规定了这个字符集中每个字符对应的码值是多少,具体的编码规则是由 UTF 系列的编码规则实现的。

UTF-8

它是一种编码规则,互联网的普及,强烈要求出现一种统一的编码方式。UTF-8 就是在互联网上使用最广泛的一种 Unicode 的实现方式(其他方式还有 UTF-16UTF-32,不过基本不用),这里的关系是:UTF-8 编码是 Unicode 的实现方式之一

UTF-8 是一种针对 Unicode 的可变长度字符编码规则,又称万国码。UTF-8 用1-4个字节编码 Unicode 字符,根据不同的字符而变化字节长度(UTF-8 编码可以容纳 2^21 个字符,总共200多万个字符)。

UTF-8 的编码规则只有两条:

  1. 对于单字节的符号,字节的第一位设为0,后面7位为这个字符的 Unicode 码,因此对于英文字母来说,UTF-8 编码和 ASCII 码是相同的。
  2. 对于 n 字节的字符(n > 1),第一个字节的前 n 位都设为 1,第 n+1 位设为 0,后面字节的前两位一律设为 10,剩下的没有提及的二进制位,全部为这个字符的 Unicode 码。

下表总结了这个编码规则,字母 x 表示可用编码的位:

UTF 字节数UTF编码方式
一个字节0xxxxxxx
两个字节110xxxxx 10xxxxxx
三个字节1110xxxx 10xxxxxx 10xxxxxx
四个字节11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

下面以汉字 为例,演示如何实现 UTF-8 编码:
已知 Unicode 编号是 U+4E25,换算成二进制是 1001110 00100101(注意,这是它的 Unicode 值,至于以什么样的二进制值存储和计算机中进行传输是通过编码方式来的) ,根据上表可以得出,存储这个字需要三个字节(两个字节的编码方式,除去首位固定的 11010,剩下的位数不够存放 1001110 00100101),即格式应该是 1110xxxx 10xxxxxx 10xxxxxx,然后,从 的最后一个二进制位开始,依次从后往前填入格式中的 x,多出的位补 0,这样就得到了 UTF-8 编码值是 11100100 10111000 10100101,换算成十六进制就是 E4B8A5

在这里插入图片描述

测试题

下面例子看你是否真的掌握了 UTF-8UnicodeASCII 码之前的关系

const buf = Buffer.from('tést')
console.log(buf)
// <Buffer 74 c3 a9 73 74>

Buffer.from(string[, encoding]),创建包含 string 的新 Bufferencoding 参数标识将 string 转换位字节时要使用的字符编码,默认为 utf8

步骤说明tést
步骤一:查找字符的 Unicode 码值U+0074U+00E9U+0073U+0074
步骤二:Unicode码值转换位二进制01110100111010010111001101110100
步骤三:二进制转换为十进制116233115116
步骤四:UTF-8编码规则(0-127的跟ascii码一样单字节表示)单字节双字节单字节单字节
步骤四:UTF-8编码值0111010011000011 101010010111001101110100
步骤五:转为16进制表示74C3 A97374
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值