Unicode编码方案概述

 

1.

前面讲过,随着计算机发展到世界各地,于是各个国家和地区各自为政,搞出了很多既兼容ASCII但又互相不兼容的各种编码方案。这样一来同一个二进制编码就有可能被解释成不同的字符,导致不同的字符集在交换数据时带来极大的不便。

比如大陆和台湾是只相隔150海里、使用着同一种语言的兄弟地区,也分别采用了不同的DBCS双字节字符集编码方案。

以前大陆地区必须装上类似于“UCDOS希望汉字系统”这样的中文处理系统专门来处理简体汉字的显示、输入问题。

而台湾地区由于采用BIG5编码方案(统一繁体字编码,俗称大五码,使用2个字节表示繁体汉字),则必须安装类似于“ET倚天汉字系统”这样的繁体中文处理系统才可以正确显示、输入繁体汉字。

因此,要想打开一个文本文件,就必须首先知道它所采用的编码方案,否则用错误的编码方案进行解码,就会出现乱码。为什么电子邮件常常出现乱码?就是因为发信人和收信人使用的编码方案不一样。

2.

想象一下,如果有一种统一的编码方案,将世界上所有语言字符都纳入其中,每一个字符都给予一个全球独一无二的编码,那么乱码问题就会消失。于是全球所有国家和民族使用的所有语言字符的统一编码方案——Unicode诞生了。

最初,由多语言软件制造商组成了统一码联盟(The Unicode Consortium,www.unicode.org),然后于1991年发布了国际统一编号的The Unicode Standard(统一码标准)字符集,习惯简称为Unicode(统一码、万国码、单一码)。

接着,国际标准化组织ISO及国际电工技术委员会IEC也于1993年联合发布了称之为Universal Multiple-Octet Coded Character Set(通用多八位组编号字符集;习惯翻译为“通用多八位编码字符集”)、简称为UCS(Universal Character Set通用字符集)的国际统一编号的ISO/IEC 10646-1字符集。

后来,统一码联盟与ISO/IEC双方都意识到世界上没有必要存在两套统一编号的通用字符集,于是进行整合,并为创立一个单一的通用字符集而协同工作。到Unicode 2.0时,Unicode字符集和UCS字符集(ISO/IEC 10646-1)基本保持了一致。

虽然现在两个项目仍都存在,并独立地公布各自的标准,但统一码联盟和ISO/IEC都同意保持两者的字符集相互兼容,并共同调整任何未来的扩展。

显然,目前Unicode的知名度要比UCS知名度大得多,已成了全球统一的通用字符集或编码方案的代名词。

 

3.

Unicode字符集的目标是涵盖目前人类使用的所有字符,并为每个字符分配唯一的字符编号(即码点编号、码点值),一一对应于编号空间(Code Space代码空间、码空间、码点空间)里的码点(Code Point代码点)。

Unicode字符集将所有字符按照使用上的频繁度划分为17个平面(Plane层面),每个平面上的编号空间有2^16=65536个码点。

(笨笨阿林原创文章,转载请注明出处)

4.

其中第0个平面BMP(Basic Multilingual Plane基本多语言平面、基本多文种平面、基本平面、平面0),基本涵盖了当今世界上正在使用中的常用字符。我们平常用到的Unicode字符,一般都是位于BMP平面上的。

BMP平面以外其他的增补平面要么用来表示一些非常特殊的字符(比如不常用的象形文字、远古时期的文字等),且多半只有专家在历史和科学领域里才会用到它们;要么被留作扩展之用。目前Unicode字符集中尚有大量编号空间未被使用。

另外,BMP平面有一个专用区(Private Use Zone):0xE000~0xF8FF(十进制57344~63743),共6400个码点,被保留为专用(私用),因而永远不会被分配给任何字符;还有一个被称为代理区(Surrogate Zone)的特殊区域:0xD800-0xDFFF(十进制55296~57343),共2048个码点,目的是用基本平面BMP中的两个码点“代理”表示BMP以外的其他增补平面的字符(解释详见后文)。

Unicode字符集中的平面与字符映射范围

5.

Unicode字符集的字符编码方式一开始规定用两个字节(即16位)来统一表示所有的字符(即UTF-16编码方式,UTF-16编码方式要早于UTF-8编码方式、UTF-32编码方式出现,详见后文)。

对于ASCII字符,与前面介绍的ANSI编码一样,Unicode也保持其原编码不变(准确地说,应该是保持其“编号不变”,因为在传统字符编码模型中,编号与编码不作区分,说“编码不变”也勉强可以),只是在UTF-16字符编码方式中将其长度由原来的8位扩展为16位(注意,这里的字符编码方式CEF还只是逻辑意义上的码元序列,不是字符编码模式CES——物理意义上的字节序列),而其他文化和语言的字符则全部重新统一编码。

由于ASCII字符只需要用到UTF-16的16位编码中的低8位,所以其高8位永远是0(实际上也只用到了低8位中的低7位,因此准确地说其高9位永远是0)。

6.

在Unicode标准最初推出的UTF-16字符编码方式中,无论是半角的英文字母,还是全角的汉字,它们都表示统一的“一个字符”,同时其编码也都是统一的“两个字节”(也因此UTF-16属于双字节码元编码方式,而Unicode标准在UTF-16字符编码方式之后所推出的UTF-8字符编码方式则属于单字节码元编码方式,两者之间的关系与区别详见后文)。

请注意这里的“字符”和“字节”两个术语意义上的不同:“字节”是一个与计算机相关的物理意义上的8位存贮单元,而“字符”则是一个与文化相关的逻辑意义上的文字符号。

7.

在Unicode标准推出之前,那些做多语言国际软件的公司遇上过很大麻烦。他们为了在不同的国家销售同一套软件,就不得不特别注意字符编码的问题。不仅要处处小心不要搞错,还要把软件中的文字在不同的字符编码中转换来转换去,而Unicode标准的出现,提供了一个很好的一揽子解决方案。

于是从Windows NT开始,微软趁机把操作系统改了一遍,把所有的核心代码都改成了采用Unicode标准的版本(实际使用的就是Unicode标准的UTF-16字符编码方式CEF所对应的UTF-16字符编码模式CES)。

从Windows NT开始,Windows系统终于无需要加装各种本土语言系统(比如“UCDOS希望汉字系统”之类的),就可以直接显示全世界上所有的字符了。当然,为了保持兼容性,对于之前的ANSI编码方案,Windows仍然是必须支持的。

(笨笨阿林原创文章,转载请注明出处)

8.

Unicode在刚开始制订UTF-16字符编码时,并没有考虑与任何一种现有的字符编码保持完全兼容(与ASCII也只能算是间接兼容或者说半兼容,毕竟ASCII字符的UTF-16编码也同样是16位的),比如GBK与Unicode在汉字的编码上完全是不一样的,没有任何一种简单的算术方法可以将文本内容在UTF-16编码和GBK编码之间进行直接转换,要转换的话只能通过查表这样低效率的笨办法一个字符对应一个字符地来进行。

即便是ASCII字符,也属于不完全兼容,因为UTF-16也是用两个字节来表示的,虽然低7位与ASCII保持了一致,其余高位的9位均只是占位的0,但毕竟还是使用了16位共两个字节编码,不同于ASCII码的单字节编码。正是鉴于此(当然除此之外还有其他原因),于是后来又设计了UTF-8字符编码方式,则保持了跟ASCII码的完全兼容。

9.

从字符集的角度上来讲,Unicode字符集不同于ASCII这样不能在增加字符的封闭字符集,而是一个开放的字符集,是可以不断增加字符的。因此Unicode字符集也在不断发展(比如随着互联网即时聊天工具的发展而流行起来的很多Emoji表情符就不断地被增加到了Unicode字符集中),理论上支持的字符数量是没有上限的,未来还可再扩展。

(注意,很多文章中,有时候称字符集,有时候称字符编码方案,大致上来讲,字符集与字符编码方案经常被视为同义词,尤其是在传统字符编码模型中。但若深究起来的话,在现代字符编码模型中,由于字符集实际上为编号字符集的简称,因此字符编码方案实际上涵盖了字符集。具体可参看前面对于现代字符编码模型的解释。)

Unicode字符集中的Emoji表情字符

10.

另外,与Unicode编码方案基本保持兼容的ISO/IEC UCS编码方案有UCS-2(2-byte Universal Character Set)和UCS-4(4-byte Universal Character Set)两种字符编码方式CEF,分别为2字节和4字节(基本上分别对应于Unicode编码方案中的UTF-16和UTF-32字符编码方式CEF)。

其中,UCS-2又被称为基本多语言平面BMP(Basic Multilingual Plane),与Unicode的基本多语言平面BMP保持了一致;而UCS-4格式用四个字节中的31位来表示一个字符,这样可表示21亿个不同的字符(2^31=2147483648;最高位为0,另有用途)。

不过,实践中UCS编码方案应用得不多,基本以Unicode编码方案为主,因此不作详细介绍。

11.

Unicode字符集不仅给每个字符根据其所在的码点分配了一个唯一的码点值(即码点编号,不严格地来讲,也勉强可认为是字符编号,注意不要跟UTF-16、UTF-8等字符编号的编码方式混淆了概念),而且赋予了一个正式的名称:在表示一个Unicode编号(或UCS编号)的十六进制数的前面加上“U+”。

比如,U+0041表示英语大写字母A,U+4E25表示汉字“严”。具体的字符对应表,可以查询unicode.org,汉字也可查询专门的中日韩汉字Unicode编码表

Unicode字符集中的U+0000~U+007F(即十进制的0~127)与ASCII字符集(即ISO/IEC 646标准)是一致的,U+0000~U+00FF(即十进制的0~255)与ISO/IEC 8859-1标准(Latin-1字符集)也是一致的。

(笨笨阿林原创文章,转载请注明出处)

预告:下一篇将重点讲解另无数人头大的字节序(大端序、小端序),敬请关注!】

刨根究底字符编码之八——Unicode编码方案概述的更多相关文章

  1. ASCII编码和Unicode编码的区别

    链接: 计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字才能处理.Unicode把所有语言都统一到一套编码里,这样就不会再有乱码问题了.Unicode标准也在不断发展,但最常用的是用两个字 ...

  2. 初学者对ASCII编码、Unicode编码、UTF-8编码的理解

    最早的计算机在设计时采用8个比特(bit)作为一个字节(byte),所以,一个字节能表示的最大的整数就是 255(二进制 11111111=十进制 255),如果要表示更大的整数,就必须用更多的字节. ...

  3. SQL Server 中怎么查看一个字母的ascii编码或者Unicode编码(转载)

    在sql中怎么查看一个字符的ascii编码或Unicode编码: SELECT ASCII('a') AS [AsciiNum]--字符获取ASCII码 SELECT UNICODE(N'a') AS ...

  4. 三种常见的编码:ASCII码、UTF-8编码、Unicode编码等字符占领的字节数

    ASCII码: 一个英文字母(不分大写和小写)占一个字节的空间.一个中文汉字占两个字节的空间. 一个二进制数字序列,在计算机中作为一个数字单元,一般为8位二进制数,换算为十进制. 最小值0,最大值25 ...

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

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

  6. VS2010与VS2013中的多字节编码与Unicode编码问题

    1. 多字节字符与单字节字符 char与wchar_t 我们知道C++基本数据类型中表示字符的有两种:char.wchar_t.  char叫多字节字符,一个char占一个字节,之所以叫多字节字符是因 ...

  7. SQL Server 中怎么查看一个字母的ascii编码或者Unicode编码

    参考文章:微信公众号文章 在sql中怎么查看一个字符的ascii编码,so easy !! select ASCII('a') SELECT CHAR(97) charNum SELECT UNICO ...

  8. Java实现 中文转换成Unicode编码 和 Unicode编码转换成中文

    想要实现中文字符转换为Unicode编码的话主要用到的是一个这样的包,自己可以去API文档里面查看下的 java.util.Properties; 直接进入主题吧,主要是 package Test01 ...

  9. 中文转换成Unicode编码 和 Unicode编码转换为中文

    前几天,遇到一个问题,就是在浏览器地址栏传递中文时,出现乱码,考虑了一下,解决方式有很多,我还是采用了转换编码的方式,将中文转换为Unicode编码,然后再解码成中文,以下是实现的过程,非常简单! p ...

随机推荐

  1. 【R.转载】apply函数族的使用方法

    为什么用apply 因为我是一个程序员,所以在最初学习R的时候,当成"又一门编程语言"来学习,但是怎么学都觉得别扭.现在我的看法倾向于,R不是一种通用型的编程语言,而是一种统计领域 ...

  2. 学Java,是自学还是去培训班学习?

    现在正在读在校的最后一个学年,想毕业后从事编程,但是感觉自己技术太差,应该是培训呢?还是去找实习?亦或是有更好的途径? 对于 Android 目前的行业趋势,不知道自己该不该坚持?还是转其他行业? 已 ...

  3. select 训练

    --1.查询"c001"课程比"c002"课程成绩高的所有学生的学号:SELECT b.sno FROM (SELECT * FROM sc WHERE cno ...

  4. Unity使用GL画线

    脚本需挂在相机上,如果你的脚本,编辑器报错了,Matrix stack full depth reached,加上这个方法试试GL.LoadPixelMatrix(); using System.Co ...

  5. seajs加载angularjs

    angularjs是自动完成模块的控制的,而seajs加载模块是异步的,所以不做修改,直接seajs加载angularjs会出错.            在这里讲下自己的解决方法 一.需要把ng-ap ...

  6. Android -- 从源码解析Handle+Looper+MessageQueue机制

    1,今天和大家一起从底层看看Handle的工作机制是什么样的,那么在引入之前我们先来了解Handle是用来干什么的 handler通俗一点讲就是用来在各个线程之间发送数据的处理对象.在任何线程中,只要 ...

  7. 京东商城首页jquery轮播特效

    <!DOCTYPE html><html> <head> <meta charset="utf-8" /> <title> ...

  8. Javascript中变量作用域(2)

    多层函数调用取变量时,无论在哪里调用,要到创建此函数的作用域中取值,如果找不到再往上一级,直到全局变量. 外面定义了很多的全局的变量,下面我们来一个个理一下. 定义三个变量a,b,c;将A1函数赋值给 ...

  9. VMware Ubuntu 安装

    最近对Linux系统有兴趣,本想装个双系统,考虑自己是以Windows为主,所以装了个虚拟机 VMware Workstation 12 Pro 版Ubuntu镜源文件下载地址:https://www ...

  10. React学习(一)父子组件通讯

    React父子组件之间通讯,利用props和state完成,首先React是单向数据流,父组件可以向子组件传递props: 实现父子组件双向数据流整体的思路是: 1,父组件可以向子组件传递props, ...