基础知识
-
编码:按照某种规则将字符储存到计算机中,如’a’用什么表示,称为
编码
-
解码:将存储在计算机中的二进制数取出,并解释成原字符,称为
解码
-
字符集:是一个系统支持的所有抽象字符的集合。就是一个表,每个符号都有对应的
编号
,例如ASCII码中,65(01000001)对应的是’A’ -
字符编码:是一套规则。在字符集拿到
编号
后,并不是简单的转成二进制数,而是根据这套规则来将编码压缩成一个更小的二进制数并储存到设备中,从而俭约了存储空间。如
'我'
这个字符在Unicode中是10010101 1010011
,保存到计算机时会 根据计算机的编码器,通过一种规则将二进制数变成另外一个二级制数进行保存(读取数据时需要按这个规则进行解码得到字符集中的二进制数,然后根据字符集查询对应的字符,如果解码和编码不对称就会导致数据会乱码,导致不可读)就像日本网站,我们打开有可能是乱码。就是因为web服务器在日本,编码格式是A,国内解码格式是B,所以导致了乱码
常用字符集
- ASCII:美国标准字符集3
- GB2312:简体中文汉字编码国家标准
- BIG5:台湾等地区繁体中文标准字符集
- GB18030:
- Unicode 标准万国码
ASCII 字符集
ASCII字符集:包括控制字符,英文字符,阿拉伯数字和西文符号
ASCII编码:一共有127个符号,所以7位(bit)就可以保存了(2*7 == 128)。为了表示更多的欧洲常用字符对ASCII进行了扩展,ASCII扩展字符集使用8位(bits)表示一个字符,共256字符
Unicode 字符集
Unicode字符集:超过十万个字符,万国码
Unicode是字符集,UTF-32/ UTF-16/ UTF-8是三种字符编码方案。
utf-8 编码
utf8是把unicode字符集的一种编码方式。
utf8把unicode字符集查询出来的字符,通过utf8编码的格式保存到计算机中
定长编码 和 变长编码
我们知道内存缓冲池里是一堆二进制数,二进制数可以对照字符集变成字符串。但是我们怎么知道如何在哪里划分这个字符的边界。例如 真
:十进制:30495
转成 二进制:01110111 00011111
,如果不知道是一个真
字,这一串编码也可能是:w
字符串
- 定长编码:就是默认所有字符都使用n个字节标识,高位补0。例如定义以3个字节保存一个字符,
真
存到内存中就是:00000000 01110111 00011111
- 优点:简单,容易解码
- 缺点:浪费内存,如果是一个
a
,那么就浪费了2个字节的内存
- 变成编码:根据字节内的几个比特来记录划分规则。例如:如果长度为1字节,那么定义首比特是
0
。如果字节是多字节,首字节以n个1+一个0开头,其余字节以10开头。(下面utf8编码步骤就是具体实例)- 优点:节约了内存
utf8编码步骤
-
先从unicode字符集获取编码,例如 ‘真’:十进制:
30495
转成 二进制:01110111 00011111
-
单字节规则(ascii字符集囊括的字节):字节的第一位设为了0,后面7位是字节的二进制数
-
多字节规则:
- 判断字符的编码范围(1-4 bytes)
- 对于
n
个字节的符号,第一个字节的前n
个设为1
,n+1
设为0
。 - 后面的
n-1
个字节前两位设为10
- 然后把符号的unicode编码的二进制数 塞入 空白的二进制位
题目: ‘真’字 1. -- unicode --> 30495 --> 01110111 00011111 --> \0x771f 他的范围在 0x0800 ~ 0xffff 间,所以是3bytes(字节) 2.3字节: 1110xxxx 10xxxxxx 10xxxxxx 3.unicode编码二进制塞入空白处: 1110xxxx --> 1110 0111 10xxxxxx --> 10 011100 10xxxxxx --> 10 011111 4.utf8存入硬盘的二进制数是: 11100111 10011100 10011111。十六进制数是:
所以每种编码的规则不同,所以存入文件的二进制数也不同
字符串是如何知道边界的
内存中有很多字符串,例如存了"abc","def"字符串。我们如何划分是2个字符串而不是"abcdef"字符串
- C语言:字符串结尾统一加上
\0
,当内存读到这一串00000000
二进制,代表了字符串结束,内存从这里划分 - Go语言:
字节序
将编码后的二进制(书籍blog通常以十六进制展示)存入存储器
‘真’字 如果用unicode码存入存储器,那么存入的值是\0x771f,需要2个字节来保存,第一个字节保存\0x77,第二字节存\0x1f 。此处就是多字节
\0x771f = \0x7700 + \0x001f
- 对于单字节(\0x00 - \0xff)来说,没有顺序可言,都是直接存入1bytes
- 对于多字节数据,在不同的处理器有不同的存放方式
- 大端序
- 小端序
- 混合序
- 高位字节:多字节排在前面的字节,例子中的\0x77
- 低位字节:多字节排在后面的字节,例子中的\0x1f
大端序
高位字节存储在最低的内存地址处。
内存地址固定是从低到高
上述例子中的大端序存储方式的结果是:
低地址 --> 高地址
\0x77 --> \0x1f
小端序
高位字节存储在最高的内存地址处。
内存地址固定是从低到高
上述例子中的小端序存储方式的结果是:
低地址 --> 高地址
\0x1f --> \0x77
混合序
参考
https://www.cnblogs.com/skynet/archive/2011/05/03/2035105.html
https://zh.wikipedia.org/wiki/%E5%AD%97%E8%8A%82%E5%BA%8F