编码规则
位与字节
计算机中的所有信息都是以二进制位0和1存储的。8位是一个字节,计算机按照字节的大小来读取和识别数据。 那么面对世界上如此多的语言,计算机如何知道当前字节意味着什么呢? ? 今天我们来学习一下计算机中字符的编码方式,会涉及到ASCII、UTF-8等。
ASCII码
首先我们看一下wiki上对它的定义:
来自 Code for 的 ASCII 是一个 for 。 、 、 和其他中的 ASCII 代码文本。 大多数 - 都是基于 ASCII,它们很多 .
粗略地说,ASCII 是美国信息交换标准代码,用于表示计算机和其他电信设备中的文本。 大家都知道,所有的计算机信息都是以二进制来计算和存储的,所以人们能够识别的字符与计算机中的二进制之间必然存在着映射关系。 ASCII是原始映射关系,也称为字符集。
例如,在ASCII中,大写字母A对应的ASCII码是65,是二进制; 阿拉伯数字0对应的ASCII码是48,即二进制; 键盘上还有一些符号,如空格32、回车13等。
ASCII最初只规定了127个字符,可以表示键盘上所有的普通符号、阿拉伯数字和英文字母。 对于英语国家来说,可以满足日常使用,所以他们将每个字节的第一位设置为0,只需要使用最后7位。
但其他欧洲国家,比如法国、葡萄牙等,无法完全用127个字符来表示,所以就使用了第一个空闲的0。因此,欧洲国家用一个字节也可以实现这一点(8位可以表示256个字符)。
ASCII字符集如下:
随着计算机在世界范围内的发展和普及,其他语言,例如中文和日文,已经无法用单字节256个字符来完整表示。 因此,出现了全球统一的编码规则。 它的作用是将各种语言的字符映射成二进制,目的与ASCII相同。
当前默认版本是UCS-2,它使用固定长度2个字节来表示字符。 6w+的字符量足以用于全球主要语言的大部分字符。 然而,提供了扩展机制,允许表示超过一百万个字符。
例如,英文字母A对应U+0041。 转换为十进制时为65,转换为二进制时为0100 0001,与ASCII码一致,只需要一个字节来表示。
例如,汉字1对应U+4e00,转换为十进制为19968,转换为二进制为0000。 该二进制有 15 位数字,需要至少 2 个字节来表示。
点击查看中文编码。
那么一个问题就出现了。 当计算机以字节为单位读取数据时,如何知道当前字节代表一个字符,还是两个连续字节代表一个字符? 如果按照方法用两个字节来表示一个字符,那么一个英文字符的第一个字节(只需要一个字节来表示,前面全部补零)全是0,对存储是巨大的浪费空间。
UTF-8
为了解决如何表示这个问题,或者说如何让计算机理解这个问题,UTF-8诞生了。 它的特点是变长编码,可以用1-4个字节来表示一个字符()。
UTF-8的规则非常简单。 它们由控制码+字符码组成。 控制码告诉计算机当前情况是单字节还是多字节,字符码与之对应。
规则1:对于单字节字符,8位的高位必须等于0,这与原来的127位ASCII码完全相同。 例如,大写字母A就有对应的二进制数。
规则 2:对于需要 n 个字节的字符
- 第一个字节:
- 高位前n位为`1`
- 第n+1位为`0`
- 其他字节:
- 高位以`10`开头
- 未提及的位使用对应的unicode补充,不足的在高位用0补充与utf-8的映射关系如下:
示例 1-ASCII
它直接兼容早期的ASCII,因此无论是ASCII编码还是UTF-8编码,ASCII字符都是一样的。
示例2-中文
对于中文来说,对应的字符集是4e00。 4e00的范围是0800~FFFF,所以对应的UTF-8是三个字节。 4e00对应的二进制为0000,加上控制码后对应的UTF-8为00,第一个字节第二个0(绿色)为补充。
附上打印对应编码的代码:
var yi = "一"
log.Printf("bytes:%v, rune:%v", []byte(yi), []rune(yi))// bytes:[228 184 128], rune:[19968]
// 其中golang里面,[]byte表示字符的utf-8编码对应的十进制,[]rune表示字符的unicode对应的十进制。
UTF-16、UTF-32 等
上面描述了文本字符到字符集的映射,编码是通过utf-8(如何读取字符集)实现的。 其中不仅有utf-8,还有其他编码方式,比如utf-16、utf-32等。
下面简单介绍一下这几种编码方式的区别。
、GBK等编码
在它诞生之前(1990年开始开发),由于ASCII表示范围有限,每个国家都开始对自己的国家语言进行编码。 例如中国于1980年发布,其扩展版本GBK较晚出现。
因为它只表示普通的数字、字母和汉字,不表示其他语言,所以用两个字节就够了,但它到汉字的映射与到汉字的映射无关。
例如,汉字“一”对应的字符集是4e00,“中”对应的字符集是D2BB。
为什么代码是乱码?
了解了编码的原理之后,你自然可以想到的是,文本编码和解码所使用的字符集是不同的。
我们来做一个小实验并验证一下。
创建一个新的 html 输入:
<html>
<head>
<meta charset="utf-8">
<title>title>
head>
<body>
123abc一二三
body>
html>
浏览器打开后显示正常,然后我们使用插件修改当前页面解码的字符集,这里修改为GBK:
修改后结果如下:
数字和字母不乱码,说明ASCII和GBK向下兼容,但汉字1、2、3出现乱码。 我们先找出这些字符对应的utf-8和gbk编码。
总结
字符集是文本符号和二进制之间的映射关系。
128位ASCII码是由数字、英文字母和普通符号组成的字符集。 256位ASCII扩展码是ASCII+一些欧洲语言字母的字符集。
/GBK是ASCII+汉字的字符集。 同样,也有其他国家特有的字符集。
它是世界上大多数字符的 ASCII+ 字符集。 为了节省空间,一般不直接使用,而是以utf-8编码解码。
引用