此文由前美团前端工程师@小鱼儿授权发布背景在日常开发中很少接触到字符的概念,大部分语言对字符的转换都已经封装的足够好,不需要开发人员过多考虑编码解码的问题 。但是字符编码又经常在开发中遇见,所以这一篇文章就是解决,到底什么是字符集以及其编码 。举个很简单的例子,调用字符串的length函数,其中的英文,汉字,emoji,长度分别是多少?length长度是如何计算的?IOS中的NSString,JAVAscript中的String在内存中的编码方式是什么?搞懂了字符编码,这些问题就迎刃而解了 。
编码、ASCII我们知道计算机只处理0和1,所有可见的文件,视频,音频等都是以二进制的形式存储和运算的 。我们用八个二进制位表示一个字节,那么一个字节就可以代表256种“字符” 。举个例子,字母“A”定义为65,用二进制表示是0100 0001 。
文章插图
这种把A转换成0100 0001的形式就是一次映射的过程 。再来看ASCII码一共有128个字符,那么就有128个映射 。一个字节就足足的可以表示了 。ASCII就是最早期的字符集 。
文章插图
字符集随着计算机的普及,需要做映射的字符越来越多,光常用汉字就几千个了,这时候ASCII码已经不够用了,涌现了很多字符集,ISO-8859,GB2312,GBK等,直到后来为了解决各个字符集各自为战的问题,分别产生了Unicode 组织和 ISO-10646工作小组,最后这两家组织也合并了,形成现如今的Unicode.
文章插图
UnicodeUnicode是一种计算行业标准,用于对世界上大多数书写系统中表示的文本进行一致的编码,表示和处理 。该标准由Unicode联盟维护,截至2019年5月,最新版本Unicode 12.1包含137994个字符的库,涵盖150个现代和历史脚本以及多个符号集和表情符号 。Unicode标准的字符库与ISO / IEC 10646同步,并且两者的代码相同 。Unicode也是一种字符集 。通常会用U+十六进制表示,可存储0000 ~ 10FFFF 共 1114112 个值,2^16(65536)个号码组成一个平面,一共有17个平面,其中第一个0号平面占了绝大部分常用的字符 。看下图可以比较直观的了解,其中每个最小的格子是一个字节即代表256个编码点,每个大格子有65536个编码点,蓝色区域是已被使用的区域,绿色是自用区,红色区域是代理区 。
文章插图
再将前三个格子放大,蓝绿色部分是汉字,棕色部分是朝鲜语,由这两张图可以最直观的了解Unicode存储空间 。Unicode的实现方式有多种,其中最常用的是UTF-8和UTF-16,下面逐一介绍两个实现原理 。
文章插图
UTF-8UTF-8是目前使用最广的Unicode编码方式,它是一种可变长的编码方式,从1个字节到4个字节不等 。下图是它的编码规则:
1.对于单字节的符号,字节的第一位设为0,后面7位为这个符号的 Unicode 码 。因此对于英语字母,UTF-8 编码和 ASCII 码是相同的 。
2.对于n字节的符号(n > 1),第一个字节的前n位都设为1,第n + 1位设为0,后面字节的前两位一律设为10 。剩下的没有提及的二进制位,全部为这个符号的 Unicode 码 。
文章插图
根据上表,解读 UTF-8 编码非常简单 。如果一个字节的第一位是0,则这个字节单独就是一个字符;如果第一位是1,则连续有多少个1,就表示当前字符占用多少个字节 。
下面,还是以汉字“严”为例,演示如何实现 UTF-8 编码 。
“严”的 Unicode 是4E25(100111000100101),根据上表,可以发现4E25处在第三行的范围内(0000 0800 - 0000 FFFF),因此“严”的 UTF-8 编码需要三个字节,即格式是1110xxxx 10xxxxxx 10xxxxxx 。然后,从“严”的最后一个二进制位开始,依次从后向前填入格式中的x,多出的位补0 。这样就得到了,“严”的 UTF-8 编码是11100100 10111000 10100101,转换成十六进制就是E4B8A5 。
优点:
1.兼容ASCII.
2.没有字节序问题 。(后面会讲到字节序)
3.对于英文编码较短,占用空间小 。
4.可变长,空间足够大
5.容错性好,中间丢失字节,后面的字节还是可以根据编码规则解码,不影响后面的字符生成 。
推荐阅读
- C语言字符串输入及输出的几种方式
- 种草药彻底根治咽炎,慢性咽炎如何才能彻底根治
- 红斑结节能彻底治好吗
- github加速利器,彻底解决github打不开
- Windows下如何彻底关闭windows defender防病毒
- 字符串查找 之 KMP算法
- java正则-取出指定字符串之间的内容
- 那些经典算法:字符串匹配算法BM算法
- proxies 1分钟搞懂什么是 JS 代理对象
- Java 常用代码汇总