理解ASCII、Unicode、utf-8、utf-16、utf-32

编码与解码

在计算机中,信息是由 0和1组成的二进制 进行传递的,将我们看到的字符转化为二进制数字的过程就是编码,反之将二进制数字转换为字符的过程是解码。

字符集

ASCII和Unicode分别是两种不同的编码方式,通过某一种编码方式进行编码所组成的集合称为字符集。如,字符通过Unicode编码所组成集合称为Unicode字符集。

字符编码

对于一个字符集来说要正确编码转码一个字符需要三个关键元素:字库表(character repertoire)、编码字符集(coded character set)、字符编码(character encoding form)。

字库表,决定了整个字符集能够展现表示的所有字符的范围。

编码字符集,即用一个编码值来表示一个字符在字库中的位置。如Unicode。

字符编码,将编码字符集和实际存储数值之间的转换关系。一般会将编码字符集的值作为编码后的值直接存储。如UTF-8。

看到这里,可能很多读者都会有和我当初一样的疑问:字库表编码字符集看来是必不可少的,那既然字库表中的每一个字符都有一个自己的序号,直接把序号作为存储内容就好了。为什么还要多此一举通过 字符编码把序号转换成另外一种存储格式呢?其实原因也比较容易理解:统一字库表的目的是为了能够涵盖世界上所有的字符,但实际使用过程中会发现真正用的上的字符相对整个字库表来说比例非常低。例如中文地区的程序几乎不会需要日语字符,而一些英语国家甚至简单的ASCII字库表就能满足基本需求。而如果把每个字符都用字库表中的序号来存储的话,每个字符就需要3个字节(这里以Unicode字库为例),这样对于原本用仅占一个字符的ASCII编码的英语地区国家显然是一个额外成本(存储体积是原来的三倍)。算的直接一些,同样一块硬盘,用ASCII可以存1500篇文章,而用3字节Unicode序号存储只能存500篇。于是就出现了UTF-8这样的变长编码。在UTF-8编码中原本只需要一个字节的ASCII字符,仍然只占一个字节。而像中文及日语这样的复杂字符就需要2个到3个字节来存储。

ASCII

由于计算机是美国人发明的,并没有考虑其他国家的字符,最早的编码方式便是ASCII。0 - 255被用来表示大小写英文字母、数字和一些符号,这个编码表被称为ASCII编码。

Unicode

Unicode编码定义了这个世界上几乎所有字符,而且Unicode还兼容了很多老版本的编码规范,例如刚刚讲过的 ASCII码。Unicode 编码 发展到今天 扩展到了 21 位。详见http://en.wikipedia.org/wiki/Unicode

Unicode也为了每个字符发了一张身份证,这张“身份证”上有一串唯一的数字ID确定了这个字符。这串数字在整个计算机的世界具有唯一性,Unicode给这串数字ID起了个名字叫 码点码点 经过映射后得到的二进制串的转换格式单位称之为 码元码点就是一串二进制数,码元 就是切分这个二进制数的方法。

Unicode的编号从 0000开始一直到 10FFFF共分为16个Plane,每个Plane中有65536个字符(正好填充2个字节,16位)。0 号平面叫做基本多文种平面( BMP, Basic Multilingual Plane ),涵盖了几乎所有你能遇到的字符,除了 emoji(emoji位于1号平面 ),其它平面叫做补充平面,大多是空的。

UTF

Unicode转换格式(Unicode Transformation Formats,即UTF),是为了解决码点在计算机中存储方式而设计的。

UTF-32

UTF-32是最好理解的一个了。UTF-32也就是说它的码元是32位,每32位去读一下码点,而码点是Unicode给字符的编码,前面也说了,最长才21位,因此每一个 UTF-32 值都可以直接表示对应的码点。

UTF-16

UTF-16的码元是16位的,也就是说每16位去读一下码点,获取码点的前16位数字,直到读取完成。由于BMP 几乎包括了所有常见字符,UTF-16 一般需要 UTF-32大约 一半的空间。至于其它平面里很少使用的码点都是用两个 16 位的码元来编码的。

UTF-8

UTF-8 使用一到四个字节来编码一个码点。从 0 到 127 的这些码点直接映射成 1 个字节(对于只包含这个范围字符的文本来说,这一点使得 UTF-8 和 ASCII 完全相同)。接下来的 1,920 个码点映射成 2 个字节,在 BMP 里所有剩下的码点需要 3 个字节。Unicode 的其他平面里的码点则需要 4 个字节。UTF-8 是基于 8 位的码元的。UTF-8 是基于 8 位的码元的,因此它并不需要关心字节顺序(因为字节就是8位的呀,其它UTF-16和UTF-32在不同的机器编译环境下需要考虑字节的顺序问题)

UTF-8的编码实现方法

UTF-8编码为变长编码。最小编码单位为一个字节。一个字节的前1-3个bit为描述性部分,后面为实际序号部分。

  • 如果一个字节的第一位为0,那么代表当前字符为单字节字符,占用一个字节的空间。0之后的所有部分代表在Unicode中的序号。

  • 如果一个字节以110开头,那么代表当前字符为双字节字符,占用2个字节的空间。110之后的所有部分代表在Unicode中的序号。且第二个字节以10开头

  • 如果一个字节以1110开头,那么代表当前字符为三字节字符,占用3个字节的空间。110之后的所有部分代表在Unicode中的序号。且第二、第三个字节以10开头

  • 如果一个字节以10开头,那么代表当前字节为多字节字符的第二个字节。10之后的所有部分代表在Unicode中的序号。

具体每个字节的特征可见下表,其中 x代表序号部分,把各个字节中的所有 x部分拼接在一起就组成了在Unicode字库中的序号

Byte1 Byte2 Byte3
0xxx xxxx    
110x xxxx 10xx xxxx  
1110 xxxx 10xx xxxx 10xx xxxx

可以得出这样一个规律:

  • 3个字节的UTF-8十六进制编码一定是以 E开头的

  • 2个字节的UTF-8十六进制编码一定是以 CD开头的

  • 1个字节的UTF-8十六进制编码一定是以比 8小的数字开头的

Emoji问题

前面也提到Emoji位于1号平面,是需要四个字节来编码的,Emoji在Unicode中位于 \u1F601- \u1F64F区段。这个显然超过了目前常用的UTF-8字符集的编码范围 \u0000- \uFFFF。Emoji表情随着IOS的普及和微信的支持越来越常见。下面就是几个常见的Emoji:

ASCII、Unicode、utf-8、utf-16、utf-32的更多相关文章

  1. ASCII、UNICODE、UTF

    在计算机中,一个字节对应8位,每位可以用0或1表示,因此一个字节可以表示256种情况. ascii 美国人用了一个字节中的后7位来表达他们常用的字符,最高位一直是0,这便是ascii码. 因此asci ...

  2. 【转】【编码】ASCII 、UNICODE和UTF-8之二

    字符发展 1. 美国 ASCII-(American standard code information interchange) 美国信息互换标准代码 范围:1-127 ; 单字 备注:前部用作控制 ...

  3. ASCII、Unicode、GBK和UTF-8字符编码的区别联系(转载)

    ASCII.Unicode.GBK和UTF-8字符编码的区别联系 转载自:http://dengo.org/archives/901 很久很久以前,有一群人,他们决定用8个可以开合的晶体管来组合成不同 ...

  4. 字符编码笔记:ASCII、Unicode、UTF-8、UTF-16、UCS、BOM、Endian

    转载:http://witmax.cn/character-encoding-notes.html 今天中午,我突然想搞清楚Unicode和UTF-8之间的关系,于是就开始在网上查资料. 结果,这个问 ...

  5. 字符编码终极笔记:ASCII、Unicode、UTF-8、UTF-16、UCS、BOM、Endian

    1.字符编码.内码,顺带介绍汉字编码 字符必须编码后才能被计算机处理.计算机使用的缺省编码方式就是计算机的内码.早期的计算机使用7位的ASCII编码,为了处理汉字,程序员设计了用于简体中文的GB231 ...

  6. 字符编码的种类:ASCII、GB2312、GBK、GB18030、Unicode、UTF-8、UTF-16、Base64

    ASCII码ASCII:https://zh.wikipedia.org/wiki/ASCIIASCII(American Standard Code for Information Intercha ...

  7. 【转】字符编码笔记:ASCII、Unicode、UTF-8 和 Base64

    1. ASCII码 我们知道,在计算机内部,所有的信息最终都表示为一个二进制的字符串.每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256种状态(-128~127),这被称为一 ...

  8. ASCII编码、Unicode编码、UTF-8

    一.区别 ASCII.Unicode 是“字符集” UTF-8 .UTF-16.UTF-32  是“编码规则” 其中: 字符集:为每一个「字符」分配一个唯一的 ID(学名为码位 / 码点 / Code ...

  9. 关于字符编码:ascii、unicode与utf-8

    转自:https://foofish.net/unicode_utf-8.html 阮一峰老师对普及计算机基础技术功不可没,但毕竟老师不是神,因此也避免不了对某些概念有一些错误的理解,<字符编码 ...

  10. ANSI、ASCII、Unicode和UTF-8编码

    来自:http://blog.163.com/yang_jianli/blog/static/161990006201371451851274/ --------------------------- ...

随机推荐

  1. LG5338/BZOJ5509/LOJ3105 「TJOI2019」甲苯先生的滚榜 Treap

    问题描述 LG5338 LOJ3105 BZOJ5509 题解 建立一棵\(\mathrm{Treap}\),把原来的\(val\)换成两个值\(ac,tim\) 原来的比较\(val_a<va ...

  2. Taro/微信小程序解析XML

    npm i xmldom PS: https://www.npmjs.com/package/xmldom https://blog.csdn.net/caojie1008/article/detai ...

  3. Burst Balloons(leetcode戳气球,困难)从指数级时间复杂度到多项式级时间复杂度的超详细优化思路(回溯到分治到动态规划)

    这道题目做了两个晚上,发现解题思路的优化过程非常有代表性.文章详细说明了如何从回溯解法改造为分治解法,以及如何由分治解法过渡到动态规划解法.解法的用时从 超时 到 超过 95.6% 提交者,到超过 9 ...

  4. fft.ntt,生成函数,各种数和各种反演

    前置知识: 一,导数 倒数其实就是函数的斜率函数 设D[f(x)]表示f(x)的导数,则满足 $$1,D[f(x)]=\lim\limits_{\delta x->\infty}\frac{f( ...

  5. Java高级工程师常见问题

    MySQL数据库调优   定位慢查询得到生产环境那些sql语句响应慢,根据执行计划进行分析调优事物管理索引结构(B+树)平衡二叉树.B树.B+树分库分表后,如何解决查询    使用第三方数据库中间件( ...

  6. swagger案例Swagger案例

    pom <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework ...

  7. Nacos配置的多环境管理

    实现多环境管理有下面几种方式 1.使用Data ID与profiles实现 在 Nacos Config Starter 中,dataId 的拼接格式为 ${prefix} - ${spring.pr ...

  8. Intellij插件之MavenHelper

    作用: 一键查看maven依赖,查看冲突的依赖,一键进行exclude依赖 插件提供地址: https://plugins.jetbrains.com/plugin/7179-maven-helper ...

  9. enum一个最不像class的class

    enum一个最不像class的classjava枚举类型是jdk5出现的.它的出现主要为了解决一些有特殊意义,已经确定的,长度不会改变的集合. //月份描述 public class Month { ...

  10. kubeadm安装kubernetes 1.16.2

    目录 简介 环境说明 安装 准备基础环境 安装docker 安装kubeadm.kubelet.kubectl 配置kubeadm-config.yaml 部署master 安装flannel网络插件 ...