`

Unicode编码详解

阅读更多

今天看到一个面试问题:Unicode 和 UTF-8 有何区别?

 

我的简单理解就是Unicode 是字符集,而UTF-8是编码集/方式,之前在HTML字符集里总结过相关问题。但是今天搜索后又有一些更深的理解,这里记录下

把这些基础写了出来,是觉得就算是基础有些还是不会,所以总结下。基础很重要,基础越熟练,你走的越快。

 

【引文】

广义的 Unicode 是一个标准,定义了一个字符集以及一系列的编码规则,即 Unicode 字符集和 UTF-8、UTF-16、UTF-32 等等编码规则。

简单来说:

Unicode 是「字符集」,符号范围是16进制

UTF-8 是「编码规则」,范围是二进制

其中:

字符集:为每一个「字符」分配一个唯一的 ID(学名为码位 / 码点 / Code Point)

编码规则:将「码位」转换为字节序列的规则(编码/解码 可以理解为 加密/解密 的过程)

也就是说unicode是字符集,而utf8是unicode的一种编码方式

 

【主体】

我今天用了一个白天的时间把这个问题好好梳理了一遍,来这里做分享。

 

一.一切的开始-----ASCII

      计算机是无法识别字母和符号的,他只能用数字来做处理,那么此时ASCII码孕育而生,所谓ASCII码,就是将英文字母和常用符号用特定的数字去表达。比如:字母A用ASCII编码是十进制的65,二进制的01000001;字符0用ASCII编码是十进制的48,二进制的00110000,注意字符'0'和整数0是不同的;

      我们可以这样理解ASCII码,她就是一个字典,是英文世界和计算机世界沟通的通道。这个通道让一开始的沟通变顺畅。就这样计算机和程序员愉快的交流着。可是随着发展问题随之而来。中文和其他世界的也要和计算机沟通,中文和其他的语言的的进入,那ASCII肯定是不够的。

      我们知道,一个字母和符号是一个字节,而一个汉字是两个字节。所以在中文输入的时候,ASCII是不能用的。一时间,编码的世界就像是进入了战国,每个地方都在制定自己编码规则。中国制定了GB2312编码,用来把中文编进去。日本把日文编到Shift_JIS里,韩国把韩文编到Euc-kr里。编码的世界混乱了。

 

二.分久必合

      计算机的实质是交流,和任何人交。所以这个分乱规则肯定是不可以的。大家一商量,把所有的字符写在一个规则下,这样Unicode出生了。Unicode包含我们现在可以用到的所有字符,Unicode也就出一个存下来所有符号的字典,重新担当起计算机世界和人类世界的翻译工作。

      到这里我再说一句,对于理解Unicode你将它要理解为字典。我们可以随时把他当做的翻译的依据。但是对于Unicode我们也是编码的。其中一开始编码方式是UCS-2。一般的汉字是两个字节,所以大多的UCS-2用两个字节来表示,但是某些偏僻的汉字和符号用4个字节。可是表示的多也会产生问题。就是我用一个英文字符的时候,我只需要用一个字节就可以存储,那么用Unicode这个字典进行转化的时候。我们知道计算机的内存在以前是很稀缺的资源,所以这种浪费资源的事我们是不会干的。

 

三.UTF-8由来

      我们为了让内存占用更加少,开始用另一种编码方式,基于Unicode让英文字符和符号占有1个字节。此时的汉子是占3~6个字节。所以在英文文档中,用UTF-8是节省空间的。还有一点值得注意,就是UTF-8和ASCII的编码在英文和一些字符的表达上是一样的。所以带来的好处就是,在一些使用ASCII编码的旧的系统和设备上,用UTF-8是可以继续使用的。

      所以会有这样的答复:UTF-8是对Unicode编码的一种编码方式

      由来原因:节省流量和硬盘

但是:一个汉字在UTF-8编码的情况下可能需要三个字节,使用gbk两个字节就足够了,所以有时候为了节省流量和硬盘,在面对中文世界时,也有使用gbk或者gbk2312编码的

     关于进制的介绍,我在文章关于进制里做了总结

 

 

 

 【END】

 最后分享下别人的答复:

 ①UTF-8是对Unicode编码的一种编码方式。

原因:节省流量和硬盘

但是:一个汉字在UTF-8编码的情况下可能需要三个字节,使用gbk两个字节就足够了,所以有时候为了节省流量和硬盘,在面对中文世界时,也有使用gbk或者gbk2312编码的

 ②Unicode就是包含所有字符的字符集,解决了世界各地每个地方所用的编码方式不一样的尴尬,让我们更好沟通。UTF-8就是为了解决Unicode存在内存问题,将Unicode再次编码的一种编码方式

 ③可以这样来理解:

      字符串是由字符构成,字符在计算机硬件中通过二进制形式存储,这种二进制形式就是编码。如果直接使用 “字符串↔️字符↔️二进制表示(编码)” ,会增加不同类型编码之间转换的复杂性。

所以引入了一个抽象层,“字符串↔️字符↔️与存储无关的表示↔️二进制表示(编码)” ,这样,可以用一种与存储无关的形式表示字符,不同的编码之间转换时可以先转换到这个抽象层,然后再转换为其他编码形式。在这里,unicode 就是 “与存储无关的表示”,utf—8 就是 “二进制表示”。

 ④计算机内只能保存101010等二进制数据,那么页面上显示的字符是如何显示出来的呢?

  一:字符集(Charset)

charset = char + set,char 是字符,set是集合,charset就是字符的集合。字符集就是是这个编码方式涵盖了哪些字符,每个字符都有一个数字序号。

  二:编码方式(Encoding)

编码方式就是一个字符要怎样编码成二进制字节序,或者反过来怎么解析。也即给你一个数字序号,要编码成几个字节,字节顺序如何,或者其他特殊规则。

  三:字形字体(Font)

根据数字序号调用字体存储的字形,就可以在页面上显示出来了。所以一个字符要显示出来,要显示成什么样子要看字体文件。

   综上所述,Unicode 只是字符集,而没有编码方式。UTF-8 是一种 Unicode 字符集的编码方式,其他还有 UTF-16,UTF-32 等。而有了字符集以及编码方式,如果系统字体是没有这个字符,也是显示不出来的。

 

 

 

【拓展】

(一)字符串与编码

    计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字才能处理。最早的计算机在设计时采用8个比特(bit)作为一个字节(byte),所以,一个字节能表示的最大的整数就是255(二进制11111111=十进制255),如果要表示更大的整数,就必须用更多的字节。比如两个字节可以表示的最大整数是65535,4个字节可以表示的最大整数是4294967295。

   由于计算机是美国人发明的,因此,最早只有127个字符被编码到计算机里,也就是大小写英文字母、数字和一些符号,这个编码表被称为ASCII编码,比如大写字母A的编码是65,小写字母z的编码是122。

但是要处理中文显然一个字节是不够的,至少需要两个字节,而且还不能和ASCII编码冲突,所以,中国制定了GB2312编码,用来把中文编进去。

   你可以想得到的是,全世界有上百种语言,日本把日文编到Shift_JIS里,韩国把韩文编到Euc-kr里,各国有各国的标准,就会不可避免地出现冲突,结果就是,在多语言混合的文本中,显示出来会有乱码。

    因此,Unicode应运而生。Unicode把所有语言都统一到一套编码里,这样就不会再有乱码问题了。

Unicode标准也在不断发展,但最常用的是用两个字节表示一个字符(如果要用到非常偏僻的字符,就需要4个字节)。现代操作系统和大多数编程语言都直接支持Unicode。

 

   现在,捋一捋ASCII编码和Unicode编码的区别:ASCII编码是1个字节,而Unicode编码通常是2个字节。

字母A用ASCII编码是十进制的65,二进制的01000001;

字符0用ASCII编码是十进制的48,二进制的00110000,注意字符'0'和整数0是不同的;

汉字中已经超出了ASCII编码的范围,用Unicode编码是十进制的20013,二进制的01001110 00101101。

你可以猜测,如果把ASCII编码的A用Unicode编码,只需要在前面补0就可以,因此,A的Unicode编码是00000000 01000001。

   新的问题又出现了:如果统一成Unicode编码,乱码问题从此消失了。但是,如果你写的文本基本上全部是英文的话,用Unicode编码比ASCII编码需要多一倍的存储空间,在存储和传输上就十分不划算。

   所以,本着节约的精神,又出现了把Unicode编码转化为“可变长编码”的UTF-8编码。UTF-8编码把一个Unicode字符根据不同的数字大小编码成1-6个字节,常用的英文字母被编码成1个字节,汉字通常是3个字节,只有很生僻的字符才会被编码成4-6个字节。如果你要传输的文本包含大量英文字符,用UTF-8编码就能节省空间:

字符 ASCII Unicode UTF-8
A 01000001 00000000 01000001 01000001
x 01001110 00101101 11100100 10111000 10101101

   从上面的表格还可以发现,UTF-8编码有一个额外的好处,就是ASCII编码实际上可以被看成是UTF-8编码的一部分,所以,大量只支持ASCII编码的历史遗留软件可以在UTF-8编码下继续工作。

 

   搞清楚了ASCII、Unicode和UTF-8的关系,我们就可以总结一下现在计算机系统通用的字符编码工作方式:

在计算机内存中,统一使用Unicode编码,当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编码。

用记事本编辑的时候,从文件读取的UTF-8字符被转换为Unicode字符到内存里,编辑完成后,保存的时候再把Unicode转换为UTF-8保存到文件:

rw-file-utf-8

浏览网页的时候,服务器会把动态生成的Unicode内容转换为UTF-8再传输到浏览器:

web-utf-8

所以你看到很多网页的源码上会有类似<meta charset="UTF-8" />的信息,表示该网页正是用的UTF-8编码。

 

 

(二)字符编码中ASCII、Unicode和UTF-8的区别

1. ASCII码

我们知道,在计算机内部,所有的信息最终都表示为一个二进制的字符串。每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256种状态,这被称为一个字节(byte)。也就是说,一个字节一共可以用来表示256种不同的状态,每一个状态对应一个符号,就是256个符号,从00000000到11111111。

上个世纪60年代,美国制定了一套字符编码,对英语字符与二进制位之间的关系,做了统一规定。这被称为ASCII码,一直沿用至今。

ASCII码一共规定了128个字符的编码,比如空格"SPACE"是32(二进制00100000),大写的字母A是65(二进制01000001)。这128个符号(包括32个不能打印出来的控制符号),只占用了一个字节的后面7位,最前面的1位统一规定为0。

 

2、非ASCII编码

英语用128个符号编码就够了,但是用来表示其他语言,128个符号是不够的。比如,在法语中,字母上方有注音符号,它就无法用ASCII码表示。于是,一些欧洲国家就决定,利用字节中闲置的最高位编入新的符号。比如,法语中的é的编码为130(二进制10000010)。这样一来,这些欧洲国家使用的编码体系,可以表示最多256个符号。

但是,这里又出现了新的问题。不同的国家有不同的字母,因此,哪怕它们都使用256个符号的编码方式,代表的字母却不一样。比如,130在法语编码中代表了é,在希伯来语编码中却代表了字母Gimel (ג),在俄语编码中又会代表另一个符号。但是不管怎样,所有这些编码方式中,0--127表示的符号是一样的,不一样的只是128--255的这一段。

至于亚洲国家的文字,使用的符号就更多了,汉字就多达10万左右。一个字节只能表示256种符号,肯定是不够的,就必须使用多个字节表达一个符号。比如,简体中文常见的编码方式是GB2312,使用两个字节表示一个汉字,所以理论上最多可以表示256x256=65536个符号。

中文编码的问题需要专文讨论,这篇笔记不涉及。这里只指出,虽然都是用多个字节表示一个符号,但是GB类的汉字编码与后文的Unicode和UTF-8是毫无关系的。

 

3.Unicode

世界上存在着多种编码方式,同一个二进制数字可以被解释成不同的符号。因此,要想打开一个文本文件,就必须知道它的编码方式,否则用错误的编码方式解读,就会出现乱码。为什么电子邮件常常出现乱码?就是因为发信人和收信人使用的编码方式不一样。

可以想象,如果有一种编码,将世界上所有的符号都纳入其中。每一个符号都给予一个独一无二的编码,那么乱码问题就会消失。这就是Unicode,就像它的名字都表示的,这是一种所有符号的编码。

Unicode当然是一个很大的集合,现在的规模可以容纳100多万个符号。每个符号的编码都不一样,比如,U+0639表示阿拉伯字母Ain,U+0041表示英语的大写字母A,U+4E25表示汉字"严"。具体的符号对应表,可以查询unicode.org,或者专门的汉字对应表。

 

4. Unicode的问题

需要注意的是,Unicode只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。

比如,汉字"严"的unicode是十六进制数4E25,转换成二进制数足足有15位(100111000100101),也就是说这个符号的表示至少需要2个字节。表示其他更大的符号,可能需要3个字节或者4个字节,甚至更多。

这里就有两个严重的问题

第一个问题是,如何才能区别Unicode和ASCII?计算机怎么知道三个字节表示一个符号,而不是分别表示三个符号呢?

第二个问题是,我们已经知道,英文字母只用一个字节表示就够了,如果Unicode统一规定,每个符号用三个或四个字节表示,那么每个英文字母前都必然有二到三个字节是0,这对于存储来说是极大的浪费,文本文件的大小会因此大出二三倍,这是无法接受的。

它们造成的结果是:1)出现了Unicode的多种存储方式,也就是说有许多种不同的二进制格式,可以用来表示Unicode。2)Unicode在很长一段时间内无法推广,直到互联网的出现。

 

5.UTF-8

互联网的普及,强烈要求出现一种统一的编码方式。UTF-8就是在互联网上使用最广的一种Unicode的实现方式。其他实现方式还包括UTF-16(字符用两个字节或四个字节表示)和UTF-32(字符用四个字节表示),不过在互联网上基本不用。重复一遍,这里的关系是,UTF-8是Unicode的实现方式之一。

UTF-8最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。

 

UTF-8的编码规则很简单,只有二条:

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

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

下表总结了编码规则,字母x表示可用编码的位。

 

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编码。

已知"严"的unicode是4E25(100111000100101),根据上表,可以发现4E25处在第三行的范围内(0000 0800-0000 FFFF),因此"严"的UTF-8编码需要三个字节,即格式是"1110xxxx 10xxxxxx 10xxxxxx"。然后,从"严"的最后一个二进制位开始,依次从后向前填入格式中的x,多出的位补0。这样就得到了,"严"的UTF-8编码是"11100100 10111000 10100101",转换成十六进制就是E4B8A5。

 

 

 

 

 

.

分享到:
评论

相关推荐

    Unicode编码和双向算法(bidi)详解.pdf

    Unicode编码方式则是指如何将这些码点转换为计算机能够处理的二进制数据。目前,最常用的Unicode编码方式是UTF-8和UTF-16。 UTF-8编码是一种可变长度的编码方式,它以字节为单位,能够根据字符的码点大小来决定使用...

    unicode编码方式详解

    Unicode 编码方式详解 Unicode 编码方式是计算机程序或数据文件中文本存储和表示的一种方式。文本是由字符组成的,字符可以是字母、数字、句点、连字号、标点符号和数学符号等。为了在计算机中存储和表示这些字符,...

    中文unicode编码表.rar

    《中文Unicode编码表详解》 Unicode编码,全称为统一码或万国码,是一种在计算机上表示文本的标准化方式,旨在解决全球不同语言字符的表示问题。中文Unicode编码表是Unicode标准的一部分,它包含了所有中文字符的...

    最全的unicode 汉字编码表

    根据提供的文件内容,我们了解到该文件包含了一段特殊的Unicode编码表示例,范围为`4e00-9fa5`,这部分是Unicode标准中用于表示常用汉字的部分。 ##### 字符范围解析 - **起始码位**:`4e00` - 表示该范围内的第...

    汉字unicode码.txt

    本文将基于“汉字unicode码.txt”文件提供的信息,深入探讨汉字Unicode编码的相关知识点。 #### 二、基础知识 1. **Unicode简介**: - Unicode是一种多字节字符编码标准,旨在为所有语言提供统一且兼容的编码方案...

    unicode编码表_txt文件

    ### Unicode编码表知识点详解 #### 一、Unicode简介与背景 **Unicode**是一种国际标准的字符编码方案,旨在为世界上所有书写系统提供统一且唯一的数字表示。它解决了不同语言文字在计算机中的编码问题,使多语言...

    维吾尔文unicode编码表

    ### 维吾尔文Unicode编码表详解 #### 标题:维吾尔文Unicode编码表 **维吾尔文Unicode编码表**是针对现代维吾尔文中使用的字母、标点符号等字符制定的一种标准化编码方案。该编码表遵循Unicode国际标准,确保了...

    Unicode编码

    ### Unicode编码详解 #### 一、引言 随着信息技术的发展,全球化的进程加快,不同语言间的交流变得越来越频繁。为了确保各种文字能够在全球范围内被准确地处理和显示,Unicode编码应运而生。本文旨在深入探讨...

    Unicode编码源代码

    **Unicode编码源代码详解** Unicode编码是一种全球统一的字符编码标准,旨在表示世界上几乎所有的文字系统,包括拉丁字母、希腊字母、汉字、日语假名等。它为每个字符分配了一个唯一的数字,称为码点,使得不同语言...

    汉转Unicode 1.0

    《汉字与Unicode编码详解及其转换应用》 在数字化的世界里,字符编码扮演着至关重要的角色,尤其是对于拥有丰富字符集的汉字来说。Unicode编码体系,作为全球通用的字符编码标准,为包括汉字在内的各种语言提供了...

    GB2312到UNICODE码表

    假设我们要将一段文本从GB2312编码转换为Unicode编码,首先需要准备一个完整的映射表,该映射表包含了所有GB2312编码与Unicode编码之间的对应关系。接着,可以编写一个程序来读取这段文本,并按照上述流程进行转换。...

    常用汉字unicode和拼音的对应关系

    本文将基于给定的文件内容,深入探讨部分常用汉字的Unicode编码与对应的拼音,帮助理解汉字编码的基础知识。 #### Unicode与汉字的关系 Unicode编码是国际上广泛采用的字符编码方案之一,旨在解决多语言环境下的...

    unicode查询器

    **Unicode编码详解** Unicode编码采用了一种二进制编码方式,将每个字符与一个唯一的数字(码点)关联。基本多文种平面(BMP)是Unicode的第一部分,包含了大部分常用字符,码点范围从U+0000到U+FFFF。对于不在BMP...

    常用字符编码详解.doc

    字符编码详解 字符编码是计算机科学中的一种基础概念,它是指将文字、符号等字符转换为计算机可以识别的二进制代码的过程。常用的字符编码有 ASCII、GB2312、GBK、GB18030 等。 1. ASCII 编码 ASCII 编码是一种 7...

    浅谈文字编码和Unicode.pdf

    2. **编码到Unicode的映射**: 计算机操作系统(如Windows)需要将这些编码数据映射到内部使用的Unicode编码,以便统一处理来自不同编码系统的文字。 3. **字体渲染**: 映射完成后,系统根据Unicode值在字体文件中...

    常用编码详解 常用编码详解 常用编码详解 常用编码详解

    本文将深入解析几种常见的编码标准,包括UCS、BMP、Unicode以及UTF-8。 首先,UCS(Universal Character Set)是一种多字节字符集,由ISO/IEC 10646-1标准定义,目的是涵盖全球各种语言的书写字符。UCS有UCS-4和UCS...

    排序编码表 解压后打开.rar

    **排序编码表与Unicode编码详解** 在信息技术领域,字符编码是一种至关重要的标准,它使得计算机能够识别、存储和处理各种语言的文字。Unicode是目前最广泛使用的字符编码标准,旨在为世界上几乎所有的文字提供一个...

Global site tag (gtag.js) - Google Analytics