Unicode(UTF&UCS)深度历险
Unicode(UTF&UCS)深度历险
计算机网络诞生后,大家慢慢地发现一个问题:一个字节放不下一个字符了!因为需要交流,本地化的文字需要能够被支持。
最初的字符集使用7bit来存储字符,因为那时只需要存下一些英文字母和符号。后来虽然扩展到使用8bit来存储一个字符了(这种方式被国际标准化组织收录,成为ISO8859-1。在字符集发展历程中国际标准化组织一直发挥着重要作用。),也还是无法存储诸如中文的字符。
混乱的年代到来了。为了存储下自己的文字,各个国家和地区(多为非拉丁语系的民族,因为这些语种字符数很庞大)各自使用两个字节即16bit来存放一个字符。他们把首字节的前2^7个位留给一个字节能存下的字符(如英文字母和标点符号),而后的位和后面的字节一起组成适用于本地文字的字符。这中方式一直沿用至今,如GB2312、GBK(此编码为微软为简体中文用户设计的)、GB18030、BIG5等。使用这种方式有一个问题:不同的数值(假如我们把字符换算成数字)在不同的字符集可能有不同的意义,甚至使用不同字体也会呈现出不同的效果!而且从一个字符集到另一个字符集的转化也会非常麻烦!
标准化一直在进行。为了解决上述麻烦,各种机构都做出了不同的努力。以微软为代表的操作系统可能更多的是提供用户可选择的语言和区域设置,并使用如CodePage(代码页,Windows操作系统对不同地区不同字符集的支持方式。如GBK为CP936)来隔离差异,国际标准化组织(ISO)编纂了ISO10646来规范和整合字符集(被成为通用字符集 Universal Character Set,UCS )。统一码联盟(由各个大型企业及组织共同维护)发布了统一码(Unicode)项目。
起初,UCS和Unicode各自为政,但1991年前后他们都发现:世界不需要两个不一样的“统一”、“通用”的字符集。所以他们联合起来维护一个字符集,现在他们的差别大概是发布新版本时使用什么字体了-_-。
UCS和Unicode都使用最大32bit来存储字符,他们(其实是一样的,不过还是区分一下)的码位(字符数)有1114112个,从0x0到0x0x10FFFF。
大家可能会奇怪,32bit最多可以表示超42亿个字符(即从0x0到0xFFFFFFFF),为什么只使用了其中这么小一部分呢?其实,这里面还有一些其他原因。
使用32bit来存储字符看起来是一件一劳永逸的方式,但如果这32bit是定宽的(即任何字符都要使用完这32bit)的话就不可避免的造成空间的浪费,程序效率也会降低!
能不能把UCS(Unicode)设计成“变宽”的呢?聪明的设计师想到了一个主意,他们发明了一种名为“统一码转换格式”即UTF的来将字符对应的数字(可能从小于127至大于100万不等)转化为多个字节来进行存储。
简单说来,UCS或Unicode只是定义了从0到1114112这些数字各自是什么字符。而如果从1~4个字节(变宽)还原出这个数字(或字符)就是UTF的事儿了。
比如“汉”字,对应数字为23383,那么要使用3字节的UTF8格式字节进行存储(原因我们下面再讲),或者1字节的UTF16或1字节的UTF32。
“汉” UTF8 = {0xE6, 0xB1, 0x89}
UTF16 = {0x6c49}
UTF32 = {0x6c49}(高位补0可省略)
Unicode字符集的划分大概有两种:按“单元(Cell)”划分(Unicode官方文档是这样分的)和按“平面(Plane)”划分。一个单元为128个字符,一个平面有65536个字符。
我们通常使用的一个平面取值为0x0到0xFFFF,这个平面被成为BMP(Basic Multilingual Plane)即“平面0”。由于这个平面只是用两个字节就可以完整表示,字符集又可以成为UCS-2(即使用2字符的“通用字符集”,UCS-4即为4字节,将UCS-4的高两位去除即为UCS-2)。
我们常用的27973个汉字都存放与平面0上,整个Unicode共定义了71226个汉字(Unicode5.0.0),平面2的43253个字符都是汉字。
UTF之间的关系和转换。上文说道,“汉”字需要3个UTF8字节来存储,这是因为要符合UTF格式的规范。
一个模版可以告诉我们UTF8是怎样存储数据的:
Unicode编码(16进制)
|
UTF-8 字节流(二进制)
|
000000 - 00007F
|
0xxxxxxx
|
000080 - 0007FF
|
110xxxxx 10xxxxxx
|
000800 - 00FFFF
|
1110xxxx 10xxxxxx 10xxxxxx
|
010000 - 10FFFF
|
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
可以看到,如果使用两个字节来存储数据,UTF8最多可以存储2^11个字符,最大的数字为0x7FF即2047,显然无法存下数字为23383的“汉”字。
而通过模版我们也可以看出Unicode的最大bit数为21。
数字向UTF的转换也很简单了,把数字换成二进制(不足21位的高位补0),然后填入对应UTF的模版(UTF16和UTF32的模版大家请自行查看,LE和BE区别在于高位和低位的位置,Windows和Linux为LE,MacOS为BE)中替换xxxxxxx就行了!很简单吧。
UTF在文件中的存储。UTF格式在文件中总有固定文件头:
UTF编码
|
Byte Order Mark
|
UTF-8
|
EF BB BF
|
UTF-16LE
|
FF FE
|
UTF-16BE
|
FE FF
|
UTF-32LE
|
FF FE 00 00
|
UTF-32BE
|
00 00 FE FF
|
如“汉”字在文件中的存储(不包括头):
Unicode编码
|
UTF-16LE
|
UTF-16BE
|
UTF32-LE
|
UTF32-BE
|
0x006C49
|
49 6C
|
6C 49
|
49 6C 00 00
|
00 00 6C 49
|
各个系统和语言对Unicode的支持:
Windows NT从底层支持Unicode(不幸的是,Windows 98只是小部分支援Unicode)。先天即被ANSI束缚的C程序设计语言通过对宽字元集的支持来支持Unicode。
Windows底层使用UTF16,Linux使用UTF32(未考证)。
C#和Java支持UTF16且是默认行为(如字符串天生为UTF16格式字符数组,Java还可以使用'\uxxxx'格式声明一个字符)。
XML及其子集HTML对UTF16支持很好,为跨平台你可以使用'&#xxxx;'来声明一个字符。
欢迎您移步我们的交流群,无聊的时候大家一起打发时间:
或者通过QQ与我联系:
(最后编辑时间2013-09-15 12:22:38)
Unicode(UTF&UCS)深度历险的更多相关文章
- 字符集和编码——Unicode(UTF&UCS)深度历险
计算机网络诞生后,大家慢慢地发现一个问题:一个字节放不下一个字符了!因为需要交流,本地化的文字需要能够被支持. 最初的字符集使用7bit来存储字符,因为那时只需要存下一些英文字母和符号.后来虽然扩展到 ...
- 各个系统和语言对Unicode的支持 字符集和编码——Unicode(UTF&UCS)深度历险
http://www.cnblogs.com/Johness/p/3322445.html 各个系统和语言对Unicode的支持: Windows NT从底层支持Unicode(不幸的是,Window ...
- SSH深度历险(十一) AOP原理及相关概念学习+xml配置实例(对比注解方式的优缺点)
接上一篇 SSH深度历险(十) AOP原理及相关概念学习+AspectJ注解方式配置spring AOP,本篇我们主要是来学习使用配置XML实现AOP 本文采用强制的CGLB代理方式 Security ...
- SSH深度历险(十) AOP原理及相关概念学习+AspectJ注解方式配置spring AOP
AOP(Aspect Oriented Programming),是面向切面编程的技术.AOP基于IoC基础,是对OOP的有益补充. AOP之所以能得到广泛应用,主要是因为它将应用系统拆分分了2个部分 ...
- 分布式Redis深度历险-Cluster
本文为分布式Redis深度历险系列的第三篇,主要内容为Redis的Cluster,也就是Redis集群功能. Redis集群是Redis官方提供的分布式方案,整个集群通过将所有数据分成16384个槽来 ...
- 分布式Redis深度历险-复制
Redis深度历险分为两个部分,单机Redis和分布式Redis. 本文为分布式Redis深度历险系列的第一篇,主要内容为Redis的复制功能. Redis的复制功能的作用和大多数分布式存储系统一样, ...
- Redis深度历险——核心原理与应用实践
高可用架构」的各位老铁们,你们好!你是否还记得上个月发布的文章中,有两篇深入讲解Redis的文章,分别是和,广大粉丝读者们对这两篇文章整体评价颇高.而我就是这两篇文章的原创作者「老钱」(钱文品),我是 ...
- 文字编码ASCII,GB2312,GBK,GB18030,UNICODE,UCS,UTF的解析
众所周知,一个文字从输入到显示到存储是有一个固定过程的,其过程为:输入码(根据输入法不同而不同)→机内码(根据语言环境不同而不同,不同的系统语言编码也不一样)→字型码(根据不同的字体而不同)→存储码( ...
- ASCII UNICODE UTF "口水文"
最近接了一个单是需要把非 UTF-8 (No BOM)编码的文件转换成 UTF-8 (No BOM),若此文件是 UTF-8 但带有 BOM ,需要转换成不带 BOM 的.于是开启了一天的阅读.首先花 ...
随机推荐
- 【高德地图API】从零开始学高德JS API(七)——定位方式大揭秘
原文:[高德地图API]从零开始学高德JS API(七)——定位方式大揭秘 摘要:关于定位,分为GPS定位和网络定位2种.GPS定位,精度较高,可达到10米,但室内不可用,且超级费电.网络定位,分为w ...
- js调用wcf 的SOA
jquery 调用wcf 的SOA架构,将三层架构运用到SOA的架构中来 经过前面3天的学习,我想大家应该对SOA的架构有了初步的了解,其实 SOA与三层架构并不冲突,而是三层架构的升级版. 来看下传 ...
- 浅谈 js 数字格式类型
原文:浅谈 js 数字格式类型 很多人也许只知道 ,123.456,0xff 之类的数字格式.其实 js 格式还有很多数字格式类型,比如 1., .1 这样的,也有 .1e2 这样的. 可能有人说这是 ...
- Hibernate制图(两)——许多-于─关系映射
上篇学习了Hibernate的基本映射,也就是单表映射,非常easy就能理解,可是对于关系数据库来说,表之间存在关系是比不可少的.关系数据库中存在的关系是通过主外键建立起来的.反应到Hibernate ...
- 工作流Jpbm4.4工作流知识点总结(工作流开发宝典)
原文:工作流Jpbm4.4工作流知识点总结(工作流开发宝典) Jbpm工作流开发过程中的一些知识点总结,方便以后开发使用! 目录: 一.工作流框架的搭建 二.工作流框架的流程开发 1.管理流程定义 ① ...
- asp.net mvc3 数据验证(二)——错误信息的自定义及其本地化
原文:asp.net mvc3 数据验证(二)--错误信息的自定义及其本地化 一.自定义错误信息 在上一篇文章中所做的验证,在界面上提示的信息都是系统自带的,有些读起来比较生硬.比如: ...
- C语言编写Windows服务程序
原文:C语言编写Windows服务程序 #include <Windows.h> #include <stdio.h> #define SLEEP_TIME 5000 // 间 ...
- 用bat启动sqlserver服务
声明下这个脚本不是我写的,忘了是从哪看到的了,在此分享给大家,因为在我的理解中技术就是用来分享的,,希望原创作者看到了不要介意. 1.创建个文本,将后缀名改成.bat 2.将下边语句粘贴进去,然后保存 ...
- MYSQL LIKE 区分大小写匹配
原文 MYSQL LIKE 区分大小写匹配 MYSQL使用LIKE匹配时默认是不区分大小写的.例:select * from table_name where a like 'wss%'select ...
- android数据库升级的措辞
在基类table增加upgrade操作: public abstract class DbBaseTable { private static final String TAG = "DbB ...