Unicode是一个巨大的字符集,给世界上所有的字符定义了一个唯一编码。其仅仅规定了每个符号的二进制代码,没有制定细化的存储规则。UTF-8、UTF-16、UTF-32才是Unicode的存储格式定义。

UTF-8

Unicode符号范围 | UTF-8编码方式

(十六进制) | (二进制)

--------------------+---------------------------------------------

0000 0000-0000 007F | 0xxxxxxx

0000 0080-0000 07FF | 110xxxxx 10xxxxxx

0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx

0001 0000-001F FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

跟据上表,解读UTF-8编码非常简单。如果一个字节的第一位是0,则这个字节单独就是一个字符;

如果第一位是1,则连续有多少个1,就表示当前字符占用多少个字节。

Little endian和Big endian

Unicode码可以采用UCS-2格式直接存储。

以汉字"严"为例,Unicode码是4E25,需要用两个字节存储,一个字节是4E,另一个字节是25。

存储的时候,4E在前,25在后,就是Big endian方式;25在前,4E在后,就是Little endian方式。

UCS-2和UCS-4

Unicode是为整合全世界的所有语言文字而诞生的。任何文字在Unicode中都对应一个值,
这个值称为代码点(code point)。代码点的值通常写成 U+ABCD 的格式。而文字和代码点之间的对应关系就是UCS-2(Universal Character Set coded in 2 octets)。顾名思义,UCS-2是用两个字节来表示代码点,其取值范围为 U+0000~U+FFFF。

为了能表示更多的文字,人们又提出了UCS-4,即用四个字节表示代码点。它的范围为 U+00000000~U+7FFFFFFF,其中 U+00000000~U+0000FFFF和UCS-2是一样的。

要注意,UCS-2和UCS-4只规定了代码点和文字之间的对应关系,并没有规定代码点在计算机中如何存储。规定存储方式的称为UTF(Unicode Transformation Format),其中应用较多的就是UTF-16和UTF-8了。

UTF-16

UTF-16由RFC2781规定,它使用两个字节来表示一个代码点。

不难猜到,UTF-16是完全对应于UCS-2的,即把UCS-2规定的代码点通过Big Endian或Little Endian方式直接保存下来。UTF-16包括三种:UTF-16,UTF-16BE(Big Endian),UTF-16LE(Little Endian)。

UTF-16BE和UTF-16LE不难理解,而UTF-16就需要通过在文件开头以名为BOM(Byte Order Mark)的字符
来表明文件是Big Endian还是Little Endian。BOM为U+FEFF这个字符。

其实BOM是个小聪明的想法。由于UCS-2没有定义U+FEFF,因此只要出现 FF FE 或者 FE FF 这样的字节序列,就可以认为它是U+FEFF,并且可以判断出是Big Endian还是Little Endian。

举个例子。“ABC”这三个字符用各种方式编码后的结果如下:

UTF-16BE

00 41 00 42 00 43

UTF-16LE

41 00 42 00 43 00

UTF-16(Big Endian)

FE FF 00 41 00 42 00 43

UTF-16(Little Endian)

FF FE 41 00 42 00 43 00

UTF-16(不带BOM)

00 41 00 42 00 43

Windows平台下默认的Unicode编码为Little Endian的UTF-16(即上述的 FF FE 41 00 42 00 43 00)。
你可以打开记事本,写上ABC,然后保存,再用二进制编辑器看看它的编码结果。

另外,UTF-16还能表示一部分的UCS-4代码点——U+10000~U+10FFFF。表示算法比较复杂,简单说明如下: 1. 从代码点U中减去0x10000,得到U'。这样U+10000~U+10FFFF就变成了 0x00000~0xFFFFF。
2. 用20位二进制数表示U'。 U'=yyyyyyyyyyxxxxxxxxxx
3. 将前10位和后10位用W1和W2表示,W1=110110yyyyyyyyyy,W2=110111xxxxxxxxxx,则 W1 = D800~DBFF,W2 = DC00~DFFF。

例如,U+12345表示为 D8 08 DF 45(UTF-16BE),或者08 D8 45 DF(UTF-16LE)。

但是由于这种算法的存在,造成UCS-2中的 U+D800~U+DFFF 变成了无定义的字符。

UTF-32

UTF-32用四个字节表示代码点,这样就可以完全表示UCS-4的所有代码点,而无需像UTF-16那样使用复杂的算法。
与UTF-16类似,UTF-32也包括UTF-32、UTF-32BE、UTF-32LE三种编码,UTF-32也同样需要BOM字符。仅用'ABC'举例:

UTF-32BE

00 00 00 41 00 00 00 42 00 00 00 43

UTF-32LE

41 00 00 00 42 00 00 00 43 00 00 00

UTF-32(Big Endian)

00 00 FE FF 00 00 00 41 00 00 00 42 00 00 00 43

UTF-32(Little Endian)

FF FE 00 00 41 00 00 00 42 00 00 00 43 00 00 00

UTF-32(不带BOM)

00 00 00 41 00 00 00 42 00 00 00 43

Unicode、UTF-8、UTF-16和UTF-32的区别的更多相关文章

  1. Unicode、UTF-8 和 ISO8859-1到底有什么区别

    说明:本文转载于新浪博客,旨在方便知识总结.原文地址:http://blog.sina.com.cn/s/blog_673c81990100t1lc.html 本文主要包括以下几个方面:编码基本知识, ...

  2. 16位模式/32位模式下PUSH指令探究——《x86汇编语言:从实模式到保护模式》读书笔记16

    一.Intel 32 位处理器的工作模式 如上图所示,Intel 32 位处理器有3种工作模式. (1)实模式:工作方式相当于一个8086 (2)保护模式:提供支持多任务环境的工作方式,建立保护机制 ...

  3. 指令集架构 x86-64 x86架构的64位拓展,向后兼容于16位及32位的x86架构

    https://zh.wikipedia.org/wiki/X86 x86泛指一系列英特尔公司用于开发处理器的指令集架构,这类处理器最早为1978年面市的"Intel 8086"C ...

  4. 8、16、32-BIT系列单片机区别与特点

    一.8位单片机 8031/8051/8751是Intel公司早期的产品 1.8031的特点 8031片内不带程序存储器ROM,使用时用户需外接程序存储器和一片逻辑电路373,外接的程序存储器多为EPR ...

  5. Unicode编码,解释UCS、UTF、BMP、BOM等名词

    (转载 谈谈Unicode编码,简要解释UCS.UTF.BMP.BOM等名词 这是一篇程序员写给程序员的趣味读物.所谓趣味是指可以比较轻松地了解一些原来不清楚的概念,增进知识,类似于打RPG游戏的升级 ...

  6. Ansi、GB2312、GBK、Unicode(utf8、16、32)

    关于ansi,一般默认为本地编码方式,中文应该是gb编码 他们之间的关系在这边文章里描写的很清楚:http://blog.csdn.net/ldanduo/article/details/820353 ...

  7. utf 8无bom和utf 8什么区别

    今天在上传CSV文件的时候,Windows下调试一切正常.妈的一到Linux下面,就出现问题,第一行数据总是读取不出来, 利用print_r()打印出读取文件的内容,发现有一个很奇怪的字符在作怪.为什 ...

  8. mov sreg, r/m16 在16位和32位编程中的区别

    总结于<X86汇编语言 从实模式到保护模式> 仅适用于X86系列处理器 1. 两者的区别: 例:mov ds, ax A.在指定16位编译模式下,产生的二进制码是 8E D8 B.在指定3 ...

  9. laravel 报错 mcrypt_decrypt(): Key of size 11 not supported by this algorithm. Only keys of sizes 16, 24 or 32 supported

    修改app/config/app.php文件 将key设置成长度为16,24,32的字符串

  10. 8位、16位、32位单片机中的“XX位”指什么?

    32位单片机的32位是指单片机的“字长”,也就是一次运算中参与运算的数据长度,这个位是指二进制位. 如果总线宽度与CPU一次处理的数据宽度相同,则这个宽度就是所说的单片机位数. 如果总线宽度与CPU一 ...

随机推荐

  1. posix and system V IPC

    轉載自 http://www1.huachu.com.cn/read/readbook.asp?bookid=10104131 http://www1.huachu.com.cn/read/readb ...

  2. Socket 与 WebSocket

    本文转载自:http://zengrong.net/post/2199.htm 1. 概述 选择了 WebSocket 技术之后,不可避免的,我要将它和其他协议以及技术做一下比较.最常见的,就是需要比 ...

  3. mysql 查看语句的执行效率

    EXPLAIN 一.用途: 1.什么时候必须为表加入索引以得到一个使用索引找到记得的更快的select 2.知道优化器是否以一个最佳次序联结表. <官方的关于explain的文档在http:// ...

  4. 使用command对象操作数据库

    1.Command对象查询数据库 protected void Button1_Click(object sender, EventArgs e) { //读取web.config节点配置 strin ...

  5. jquery控制文字内容溢出用点点点(…)省略号表示

    jQuery限制字符字数的方法 $(function(){ //限制字符个数 $(“.text”).each(function(){ var maxwidth=23; if($(this).text( ...

  6. Debug与Release的区别

    Debug版本包括调试信息,所以要比Release版本大很多(可能大数百K至数M).至于是否需要DLL支持,主要看你采用的编译选项.如果是基于ATL的,则Debug和Release版本对DLL的要求差 ...

  7. Java中的try,catch,finally

    讲解的是关于java中关于try.catch.finally中一些问题 下面看一个例子(例1),来讲解java里面中try.catch.finally的处理流程 public class TryCat ...

  8. load/get延迟加载和及时加载

    load和get方法的区别: Session.load/get方法均可以根据指定的实体类和id从数据库读取记录,并返回与之对应的实体对象. 区别在于: 如果未能发现符合条件的记录,get方法返回nul ...

  9. Quartz.net 的简单使用,创建定时任务

    ISchedulerFactory sf = new StdSchedulerFactory(); sched = sf.GetScheduler(); JobDetail job = new Job ...

  10. JAVA6开发WebService (三)——几个概念

    转载自http://wuhongyu.iteye.com/blog/808922 要了解WebService,光能写代码不行啊,这说说WebService最基本的概念. 首先WebService要知道 ...