unicode, utf-8 都是什么玩意

在学习golang的过程中, 发现golang中的字符串可以用切片来访问, 访问的是字节, 而用range来访问, 得到的是字符
于是引申出一个问题: 字节数组怎么字符打印的?
一开始我以为是通过分隔符, 但是最终发现却没有, 是用的编码
那么本文来简单快速总结一下编码吧, 看看unicode, utf-8都是些什么玩意

什么是编码

  • 将int与字符一一对应, 就是编码 (个人理解: 给字符编号)
  • 键入int, 就能打印出对应的字符
  • int用二进制来表示

ascll

  • 熟悉的ascll, 美国信息交换标准代码
  • ascll是最早的
  • 7bit, 128个字符, 表示能力有限

unicode

  • 为了解决ascll不够的问题
  • 最全
  • 32bit, 4个字节, 超过12w字符
  • 但是太多, 太大了, 所以一般不用它

utf-8

  • 既要全, 又要短(存储空间小)
  • 变长编码,
  • 使用1到4个字节来表示每个unicode码点, ascll1个字节, 常用字符部分, 2-3个字节, 最长的4个字节
  • 每个符号编码后第一个字节的高端bit位用于表示编码总共有多少个字节

utf-8的规则

  • 如果第一个字节的高端bit为0,则表示对应7bit的ASCII字符,ASCII字符每个字符依然是一个字节,和传统的ASCII编码兼容。如果第一个字节的高端bit是110,则说明需要2个字节;后续的每个高端bit都以10开头.
  • 具体规则如下
0xxxxxxx                             runes 0-127    (ASCII)
110xxxxx 10xxxxxx                    128-2047       (values <128 unused)
1110xxxx 10xxxxxx 10xxxxxx           2048-65535     (values <2048 unused)
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx  65536-0x10ffff (other values unused)

我们来找个实际的例子来看看

对于测试test这个字符串
它的情况如下

字符: 27979 35797 116 101 115 116 
字节: 230 181 139 232 175 149 116 101 115 116 

230的二进制是11100110, 说明是3个字节, 然后后面的181,和139都是10`开头的, 然后232同理

可以看到, 中文字符这里占了三个字节, 而英文字母是一个字节, 比如116就是01110100, 一个字节

关于utf-8

  • 节省空间的原因在于变长
  • 每个字符的可用空间变少, eg: 对于4个字节的来说, 有效bit是3+6x3 = 21bit, 对于3个字节, 4+ 6x2 = 16个bit, 利用率随着字节数变多, 而降低,
  • 但是, 多字节的字符用的很少其实 , 主要还是1个字节的和2-3个字节的
  • 保证了完整性的同时, 牺牲了空间效率, 但又因为高频使用部分局限, 所以又保证了部分空间效率

猜你喜欢

转载自blog.csdn.net/qq_34687559/article/details/120154168