很久以前发在他处的一篇博文,今天翻出来重新整理了一下

Unicode 字符集 共分为 17 个平面(plane), 分别对应 U+xx0000 - U+xxFFFF 的 code points, 其中 xx := 00 - 10。其中第 0 平面不包含为 UTF-16 编码保留的 U+D800 - U+DFFF。第0平面包含了最常用的字符,被成为 Basic Multilingual Plane 或 BMP (基本多语言平面)。

Unicode 在编码上有多种实现,常见的有 UTF-8, UTF-16, UCS-2(已过时), UTF-32(UCS-4)等。

UTF-8 编码

UTF-8是一种变长、多字节编码方式,可以表示所有Unicode字符码点(code point),并且与ASCII兼容。UTF-8使用字节作编码单元(code unit),用一个或多个字节编码一个Unicode字符,其中使用一个字节编码的字符与 ASCII 相同。UTF-8编码中不同含义的字节模式:

  1. 0xxxxxxx ASCII字符
  2. 10xxxxxx 多字节字符的非首编码单元
  3. 110xxxxx 双字节字符的首个编码单元
  4. 1110xxxx 三字节字符的首个编码单元
  5. 11110xxx 四字节字符的首个编码单元
  6. 111110xx 五字节字符的首个编码单元
  7. 1111110x 六字节字符的首个编码单元

例如元符号 U+00A5( ¥ ),二进制表示为 10100101,共8位,因为UTF-8编码除首字节外其它字节都必须以 10 开头,所以每字节有效位为6位,那么 U+00A5 的最后一个字节应该是 10 100101,此外还剩下的两个比特位由双字节字符的首字节模式 110xxxxx 即可完全容纳。 因些U+00A5 符合双字符编码要求,编码结果为 11000010 10100101 即 0xC2B5。

可以看到 UTF-8 实际上是比较浪费空间的,理论上非首编码单元完全可以不必使用固定的 10 前缀,而是利用整个编译单元保存8位字符数据,从而大大减小编码结果的体积。但UTF-8选择了牺牲空间利用率来换取更高的容错能力,当一大段 UTF-8 编码的内容中出现一两个字节的错误时,解码器可以快速跳过错误字符,找到下一个字符的编码首字节(必定以 110, 1110, 11110, .... 打头)

注:一些 Windows 程序在保存 UTF-8 编码文本文件时会在开头添加 0xEF, 0xBB, 0xBF 序列(貌似这个序列在little-endian与big-endian的机器上顺序还是相反的),一般称为 UTF-8 BOM (Byte Order Mark),当然事实上其与字节顺序无关 -- 因为 UTF-8 本身就以字节为单元 -- 而是用于推断文件的编码方式是否为 UTF-8的。 标准并未规定UTF-8这种文件头标识方式,而BOM在标准中是用来判定UTF-16的字符顺序的(而不是编译方式本身,详见下文)。 但由于微软大力推行这种标记方式,致使行业中的各种解码程序不得不与之兼容。

UTF-16

UTF-16 也是变长多字节编码,并可表示所有 Unicode 字符码点(code point),但以双字节(字)为编码单元。UTF-16的编码原则如下:

  1. BMP: 使用一个双字节编码单元,字符码点(code point)的数字值与编码单元的数字值相等一一对应。
  2. 平面 1-10: 使用两个编码单元共四个字节表示一个字符,规则如下:
    1. 字符值减去 0x10000, 结果为 0 - 0xFFFFF 之间20位长的数字,我们暂记为 n 吧。
    2. 取出 n 的前10位,加上 0xD800 结果在 0xD800 - 0xDBFF 之间作为第一个编码单元,也称为前导代理(lead surrogate)。
    3. 取出 n 的后10位,加上 0xDC00 结果在 0xDC00 - 0xDFFF 之间作为第二个编码单元,也称为断后代理(trail surrogate)。

比如字符 U+00A5( ¥ ),属于BMP,编码后为双字节的 0x00A5。

字符 U+201D3 (”3),二进制 10 0000 0001 1101 0011 ,共14个二进制位,不属于BMP,需要使用两个编码单元(4字节)来编码表示, 根据原则2,201D3 - 10000 = 101D3,20位二进制码为 0001 0000 0001 1101 0011 ,前10位为 0001 0000 00 即 0x40,加上 0xD800 得到 lead surrogate 0xD840;后10位为01 1101 0011即0x1D3,加上 0xDC00 得到 trial surrogate 0xDDD3。最后得到UTF-16编码为 0xD840, 0xDDD3。

UTF-16使用双字节编码单元,因些存在字节顺序的问题,可以使用字节顺序标记(Byte Order Mark 或 BOM)来帮助确定字节顺序,即将一个特殊Unicode字符U+FEFF(零宽不断行空白 Zero-width non-breaking space 或 ZWNBSP)置于第一个真正的字符之前, 如果解码程序以自己假定的字节顺序读到了 U+FFFE (这是个保留的非字符值),解码程序应该尝试进行字节交换。 如果没有检测到BOM,标准要求解码程序默认使用 big-endian, 但实际应用大多假定 little-endian, 因为windows默认这样干。字节顺序也可有通过编码名称 UTF-16BE 和 UTF-16LE 区别。

除UTF-16外,UCS-2也是16位编码单元,但不支持双编码单元组合,也就不能表示所有 Unicode 字符。 目前该编码方式已被标记为过时。

UTF-32/UCS-4

这个就不必细说了,编码结果对应Unicode的code point。

C/C++ 中的字符类型与编码方式 [仅个人理解,有待核实] char 类型的字符串一般以代码文件的编码方式处理,比如 UTF-8 保存的 c 代码文件中的 char 字符串使用 UTF-8 编码;而以 GB18030 编码保存代码文件中的字符串使用 GB18030 编码。 而使用 UTF-16 或其它非ASCII兼容的编码保存的代码文件中的字符编码本人未弄清楚。 wchar_t 类型的字符串以 UTF-16(Windows 下) 或 UTF-32(Unix/Linux下) 编码,常量声明方式为 L"string content",即字符串常量前边加L前缀。

Unicode 字符集及UTF-8 UTF-16编码的更多相关文章

  1. zzy:java采用的是16位的Unicode字符集作为编码方式------理解

    java语言使用16位的Unicode字符集作为编码方式,是疯狂Java中的原话. 1,编码方式只是针对字符类型的(不包括字符串类,数值类型int等,这些只是在解释[执行]的时候放到Jvm的不同内存块 ...

  2. 刨根究底字符编码之十——Unicode字符集的字符编码方式CEF

    Unicode字符集的字符编码方式CEF 一.字符编码方式CEF的选择 1. 由于Unicode字符集非常大,有些字符的编号(码点值)需要两个或两个以上字节来表示,而要对这样的编号进行编码,也必须使用 ...

  3. 刨根究底字符编码之十——Unicode字符集的编码方式以及码点、码元

    Unicode字符集的编码方式以及码点.码元 一.字符编码方式CEF的选择 1. 由于Unicode字符集非常大,有些字符的编号(码点值)需要两个或两个以上字节来表示,而要对这样的编号进行编码,也必须 ...

  4. Unicode字符集,utf8编码,base64编码简单了解

    Unicode字符集,utf8编码,base64编码简单了解 Unicode字符集,ASCII,GB2312编码集合等,类似于不同的字典,不同的字符的编码,类似于字典中的字在哪一个页哪一排. 当不同系 ...

  5. 多字节字符集与Unicode字符集

    在计算机中字符通常并不是保存为图像,每个字符都是使用一个编码来表示的,而每个字符究竟使用哪个编码代表,要取决于使用哪个字符集(charset). 多字节字符集: 在最初的时候,Internet上只有一 ...

  6. Unicode规范中的BOM 和 ISO8891-1编码

    Unicode规范中的BOM Unicode规范中有一个BOM的概念.BOM——Byte Order Mark,就是字节序标记.在这里找到一段关于BOM的说明: 在UCS 编码中有一个叫做" ...

  7. C语言:Unicode字符集

    Unicode 也称为统一码.万国码:看名字就知道,Unicode 希望统一所有国家的字符编码.Unicode 于 1994 年正式公布第一个版本,现在的规模可以容纳 100 多万个符号,是一个很大的 ...

  8. 《windows核心编程系列》二谈谈ANSI和Unicode字符集 .

    http://blog.csdn.net/ithzhang/article/details/7916732转载请注明出处!! 第二章:字符和字符串处理 使用vc编程时项目-->属性-->常 ...

  9. 关于Unicode字符集

    最初的unicode编码是固定长度的,16位,也就是2两个字节代表一个字符,这样一共可以表示65536个字符.显然,这样要表示各种语言中所有的字符是远远不够的.Unicode4.0规范考虑到了这种情况 ...

随机推荐

  1. maven发布的资源文件到tomcat项目下

    问题:项目中有hibernate的资源文件,src/main/java和src/main/resources都有这些文件,当启动项目时发现出错.但是src/main/java已经修改好了, 经查tom ...

  2. linux 命令学习(4)

    Linux中常用的关机和重新启动命令有shutdown.halt.reboot以及init,它们都可以达到关机和重新启动的目的,但是每个命令的内部工作过程是不同的,下面将逐一进行介绍. 1. shut ...

  3. iOS菜鸟之苹果开发者账号的注册

    大家一起来讨论讨论苹果开发者账号的注册(主要是以公司的开发者账号为例),前段时间公司要求注册开发者账号,于是我就特地看了看相关的帖子.这里简单给大家总结一下具体的流程. 首先你要登陆这个网址,进去之后 ...

  4. cas sso单点登录系列8_抛弃Https让Cas以Http协议提供单点登录服务

    转:http://blog.csdn.net/ycyk_168/article/details/18668951 本文环境: 1.apache-tomcat-7.0.50-windows-x86 2. ...

  5. POJ刷题记录 (。・`ω´・)(Progress:6/50)

    1743:前后作差可以转化成不可重叠最长公共字串问题,运用后缀数组解决(参考罗穗骞神犇的论文) #include <cstdio> #include <cstring> #in ...

  6. 基于jQuery选择器的整理集合

    jquery对象访问1.each(callback):以每个匹配的元素作为上下文来执行一个函数,return false;停止循环;return true;跳至下一个循环. 来个实例 : 代码如下: ...

  7. 移动Web开发,4行代码检测浏览器是否支持position:fixed

    不废话,直接上代码 var div = document.createElement('div'); div.style.cssText = 'display:none;position:fixed; ...

  8. Jquery 简单的Tab选项卡特效

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  9. Python自动化运维之26、Web框架本质、MVC与MTV

    一.Web框架本质 众所周知,对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端. #!/usr/bin/env python #coding:ut ...

  10. Java中间件

    传统的HTML已经满足不了如今web系统的诸多的功能需求,建立一个交互式的Web,便诞生了各种Web开发语言,如ASP,JSP,PHP等,这些语言与传统的语言有着密切的联系,如JSP基于Java语言. ...