UTF-8是unicode的一种具体实现。
Unicode 是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。1990年开始研发,1994年正式公布。它是一种标准,规定了每个字符对应的二进制数,或者称它是一个具体大的映射。但是unicode并没有规定字符对应的二进制数怎么存储,比如字母可能对应的数字很小,那么转换为二进制数需要8位(一个字节)就够了。但是汉字就需要14/15/16位才能表示下也就是最少需要两个字节,甚至有些字符需要三个字节才能表示。
UTF-8就是unicode的一种具体实现,它采用变长方式存储字符,比如需要一个字节就可以表示的字符那就用一位存储,需要二位字节表示的用两个字节存储。这样就可以尽量缩短文件大小,方便文件存储、传输。
UTF-8的编码规则很简单,只有二条:
1)对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。
2)对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。
eg:
Unicode符号范围 | UTF-8编码方式
(十六进制) | (二进制)
--------------------±--------------------------------------------
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
跟据上表,解读UTF-8编码非常简单。如果一个字节的第一位是0,则这个字节单独就是一个字符;如果第一位是1,则连续有多少个1,就表示当前字符占用多少个字节。
另外,当一个字符需要两个以上字节表示时,比如用“中”的unicode编码是D6 D0,那么具体存储(传输)的时候是D0在前还是D6在前都是可以的,因此就产生了Little endian和Big endian。Little endian就是D0 D6的存储,Big endian就是D6 D0的方式。
总之,你可以这么认为,unicode就好比Java中的接口,它只规定一些规则内容方法,UTF-8是具体的实现,考虑了很多实际的东西。

想必做过爬虫的同学肯定被编码问题困扰过,有 UTF-8、GBK、Unicode 等等编码方式,但你真的了解其中的原理吗?下面我们就来了解一下 Unicode 和 UTF-8 编码到底有什么关系。

要弄清 Unicode 与 UTF-8 的关系,我们还得从他们的来源说起,下来我们从刚开始的编码说起,直到 Unicode 的出现,我们就会感觉到他们之间的关系

ASCII码

我们都知道,在计算机的世界里,信息的表示方式只有 0 和 1,但是我们人类信息表示的方式却与之大不相同,很多时候是用语言文字、图像、声音等传递信息的。

那么我们怎样将其转化为二进制存储到计算机中,这个过程我们称之为编码。更广义地讲就是把信息从一种形式转化为另一种形式的过程。

我们知道一个二进制有两种状态:”0” 状态 和 “1”状态,那么它就可以代表两种不同的东西,我们想赋予它什么含义,就赋予什么含义,比如说我规定,“0” 代表 “吃过了”, “1”代表 “还没吃”。

这样,我们就相当于把现实生活中的信息编码成二进制数字了,并且这个例子中是一位二进制数字,那么 2 位二进制数可以代表多少种情况能?对,是四种,2^2,分别是 00、01、10、11,那 7 种呢?答案是 2^7=128。

我们知道,在计算机中每八个二进制位组成了一个字节(Byte),计算机存储的最小单位就是字节,字节如下图所示 :

所以早期人们用 8 位二进制来编码英文字母(最前面的一位是 0),也就是说,将英文字母和一些常用的字符和这 128 中二进制 0、1 串一一对应起来,比如说 大写字母“A”所对应的二进制位“01000001”,转换为十六进制为 41。

在美国,这 128 是够了,但是其他国家不答应啊,他们的字符和英文是有出入的,比如在法语中在字母上有注音符号,如 é ,这个怎么表示成二进制?

所以各个国家就决定把字节中最前面未使用的那一个位拿来使用,原来的 128 种状态就变成了 256 种状态,比如 é 就被编码成 130(二进制的 10000010)。

为了保持与 ASCII 码的兼容性,一般最高为为 0 时和原来的 ASCII 码相同,最高位为 1 的时候,各个国家自己给后面的位 (1xxx xxxx) 赋予他们国家的字符意义。

但是这样一来又有问题出现了,不同国家对新增的 128 个数字赋予了不同的含义,比如说 130 在法语中代表了 é,但是在希伯来语中却代表了字母 Gimel(这不是希伯来字母,只是读音翻译成英文的形式)具体的希伯来字母 Gimel 看下图

所以这就成了不同国家有不同国家的编码方式,所以如果给你一串二进制数,你想要解码,就必须知道它的编码方式,不然就会出现我们有时候看到的乱码 。

Unicode的出现

Unicode 为世界上所有字符都分配了一个唯一的数字编号,这个编号范围从 0x000000 到 0x10FFFF (十六进制),有 110 多万,每个字符都有一个唯一的 Unicode 编号,这个编号一般写成 16 进制,在前面加上 U+。例如:“马”的 Unicode 是U+9A6C。

Unicode 就相当于一张表,建立了字符与编号之间的联系

它是一种规定,Unicode 本身只规定了每个字符的数字编号是多少,并没有规定这个编号如何存储。

有的人会说了,那我可以直接把 Unicode 编号直接转换成二进制进行存储,是的,你可以,但是这个就需要人为的规定了,而 Unicode 并没有说这样弄,因为除了你这种直接转换成二进制的方案外,还有其他方案,接下来我们会逐一看到。

编号怎么对应到二进制表示呢?有多种方案:主要有 UTF-8,UTF-16,UTF-32。

1、UTF-32 

先来看简单的 UTF-32

这个就是字符所对应编号的整数二进制形式,四个字节。这个就是直接转换。 比如马的 Unicode 为:U+9A6C,那么直接转化为二进制,它的表示就为:1001 1010 0110 1100。

这里需要说明的是,转换成二进制后计算机存储的问题,我们知道,计算机在存储器中排列字节有两种方式:大端法和小端法,大端法就是将高位字节放到底地址处,比如 0x1234, 计算机用两个字节存储,一个是高位字节 0x12,一个是低位字节 0x34,它的存储方式为下:

UTF-32 用四个字节表示,处理单元为四个字节(一次拿到四个字节进行处理),如果不分大小端的话,那么就会出现解读错误,比如我们一次要处理四个字节 12 34 56 78,这四个字节是表示 0x12 34 56 78 还是表示 0x78 56 34 12?不同的解释最终表示的值不一样。

我们可以根据他们高低字节的存储位置来判断他们所代表的含义,所以在编码方式中有 UTF-32BE 和 UTF-32LE,分别对应大端和小端,来正确地解释多个字节(这里是四个字节)的含义。

2、UTF-16 

UTF-16 使用变长字节表示

① 对于编号在 U+0000 到 U+FFFF 的字符(常用字符集),直接用两个字节表示。 
② 编号在 U+10000 到 U+10FFFF 之间的字符,需要用四个字节表示。

同样,UTF-16 也有字节的顺序问题(大小端),所以就有 UTF-16BE 表示大端,UTF-16LE 表示小端。

3、UTF-8 

UTF-8 就是使用变长字节表示,顾名思义,就是使用的字节数可变,这个变化是根据 Unicode 编号的大小有关,编号小的使用的字节就少,编号大的使用的字节就多。使用的字节个数从 1 到 4 个不等。

UTF-8 的编码规则是:

① 对于单字节的符号,字节的第一位设为 0,后面的7位为这个符号的 Unicode 码,因此对于英文字母,UTF-8 编码和 ASCII 码是相同的。

② 对于n字节的符号(n>1),第一个字节的前 n 位都设为 1,第 n+1 位设为 0,后面字节的前两位一律设为 10,剩下的没有提及的二进制位,全部为这个符号的 Unicode 码 。

举个例子:比如说一个字符的 Unicode 编码是 130,显然按照 UTF-8 的规则一个字节是表示不了它(因为如果是一个字节的话前面的一位必须是 0),所以需要两个字节(n = 2)。

根据规则,第一个字节的前 2 位都设为 1,第 3(2+1) 位设为 0,则第一个字节为:110X XXXX,后面字节的前两位一律设为 10,后面只剩下一个字节,所以后面的字节为:10XX XXXX。

所以它的格式为 110XXXXX 10XXXXXX 。

下面我们来具体看看具体的 Unicode 编号范围与对应的 UTF-8 二进制格式

那么对于一个具体的 Unicode 编号,具体怎么进行 UTF-8 的编码呢?

首先找到该 Unicode 编号所在的编号范围,进而可以找到与之对应的二进制格式,然后将该 Unicode 编号转化为二进制数(去掉高位的 0),最后将该二进制数从右向左依次填入二进制格式的 X 中,如果还有 X 未填,则设为 0 。

比如:“马”的 Unicode 编号是:0x9A6C,整数编号是 39532,对应第三个范围(2048 - 65535),其格式为:1110XXXX 10XXXXXX 10XXXXXX,39532 对应的二进制是 1001 1010 0110 1100,将二进制填入进入就为:

11101001 10101001 10101100 。

由于 UTF-8 的处理单元为一个字节(也就是一次处理一个字节),所以处理器在处理的时候就不需要考虑这一个字节的存储是在高位还是在低位,直接拿到这个字节进行处理就行了,因为大小端是针对大于一个字节的数的存储问题而言的。

综上所述,UTF-8、UTF-16、UTF-32 都是 Unicode 的一种实现。

转载自:https://blog.csdn.net/zhusongziye/article/details/84261211

更多参考:
https://blog.csdn.net/code_for_fun/article/details/50506122
https://www.cnblogs.com/echobfy/p/3854307.html
https://www.cnblogs.com/playboysnow/articles/4778494.html

你真的懂 Unicode 和 UTF-8 是什么关系吗?来看看这个就彻底懂了!相关推荐

  1. ASCII Unicode GBK UTF的联系

    快下班时,爱问问题的小朋友Nico又问了一个问题: "sqlserver里面有char和nchar,那个n据说是指unicode的数据,这个是什么意思." 并不是所有简单的问题都很 ...

  2. 计算机基础知识之Unicode-彻底弄懂 Unicode 编码

    彻底弄懂 Unicode 编码 前言 为什么要有编码? 大家需要明确的是在计算机里所有的数据都是字节的形式存储.处理的.我们需要这些字节来表示计算机里的信息.但是这些字节本身又是没有任何意义的,所以我 ...

  3. Unicode、UTF-8 和 ISO8859-1到底有什么区别(转载)

    本文主要包括以下几个方面:编码基本知识,java,系统软件,url,工具软件等. 在下面的描述中,将以"中文"两个字为例,经查表可以知道其GB2312编码是"d6d0 c ...

  4. 字符集ASCII、GBK、UNICODE、UTF在储存字符时的区别

    ASCII编码(American Standard Code for Information Interchange,美国信息互换标准代码),使用127个8进制字节表示英文和半角字符. GBK (Gu ...

  5. 大数据真的很牛B吗?不不不,10分钟让你读懂它

    xiaoyu Ma:大数据的讨论,大数据本身是个很宽泛的概念,Hadoop生态圈(或者泛生态圈)基本上都是为了处理超过单机尺度的数据处理而诞生的.你可以把它比作一个厨房所以需要的各种工具.锅碗瓢盆,各 ...

  6. 一篇能看懂unicode的文章

    @YangYang48 unicode 在开始这个问题之前首先提出几个问题,希望读者能带着这几个问题去看这篇文章 问题1 一个汉字究竟占几个字节? 问题2 我在网页上能看到一些外文像韩文日文或者特殊符 ...

  7. Unicode、UTF 和 ISO-8859-1等编码方式详解与浏览器URL编码

    将字符转换为二进制码的过程,我们称为编码,将二进制码转换为字符的过程,我们称为解码. 编码和解码时所采用的规则,我们称为字符集 常见的字符集: ASCII - 美国人编码,使用7位来对美国常用的字符进 ...

  8. unicode、utf区别

    字符集 首先,我们要明确2个概念,字符集和字符编码. 字符集:ASCII.GB2312.GBK.Unicode 字符编码:UTF-8.UTF-16.UTF-32 由于ASCII.GB2312.GBK不 ...

  9. 简单介绍Unicode和utf编码

    Unicode是一个字符集,码点范围为U+0000~U+10FFFF,共有1+2^20的取值空间,可以容纳超过100万个字符,至少需要21Bit(位)编码空间. 码点的意思是,这个字符集内的字符按序编 ...

最新文章

  1. XGBOOST带试验源码
  2. 美国一大型数据中心将24h由光伏+储能供电
  3. symantec 5220牛刀小试系列(二)
  4. 写在这个公众号关注者达到7000之际,Jerry有话对大家说
  5. 前端学习(2345):项目目录简单介绍
  6. 扎克伯格拒绝参加加拿大议会 或因藐视罪名被拘留
  7. Deepin - 环境配置及软件安装卸载记录(Debain镜像源)
  8. Sentaurus 入门之二视频教程合集
  9. 推荐几个免费的ppt模板网站
  10. linux开发板通过网线连接电脑(win10)连接网络问题
  11. IDEA集成camunda-modeler
  12. 微信群活码的原理及其作用,以及活码怎么使用
  13. tensorflow 2.0 基础操作 之 不同 dim 对应的具体含义
  14. uni-app H5 上传图片
  15. JSON转JS对象,JS对象转JSON
  16. [蓝桥杯][算法提高VIP]我们的征途是星辰大海
  17. Docker 退出容器但不关闭当前容器
  18. 潭州教育python学院_潭州什么学院,直播python课程内幕
  19. php中sql语句字符串截取字符串,sql语句的截取字符串下标是从1开始
  20. cxf 创建webservice

热门文章

  1. redis队列list时效性过期解决方案
  2. error RC2175
  3. 50个你离不开的 CLI 工具
  4. 《老喻的人生算法课》笔记
  5. 看陈广老师c#参考视频总结(第六篇)
  6. forest -http工具
  7. 虚拟机中连接外部无线网络
  8. iOS 获取手机序列号
  9. 计算机和微型计算机有什么不同,小型计算机和微型计算机是同一个吗?
  10. 台式机和便携机属于小型计算机吗,计算机的分类方法有多种,按照计算机的性能和用途来分类,台式机和便携机均属于传统的小型计算机。...