Unicode 字符集及UTF-8 UTF-16编码
很久以前发在他处的一篇博文,今天翻出来重新整理了一下
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编码中不同含义的字节模式:
- 0xxxxxxx ASCII字符
- 10xxxxxx 多字节字符的非首编码单元
- 110xxxxx 双字节字符的首个编码单元
- 1110xxxx 三字节字符的首个编码单元
- 11110xxx 四字节字符的首个编码单元
- 111110xx 五字节字符的首个编码单元
- 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的编码原则如下:
- BMP: 使用一个双字节编码单元,字符码点(code point)的数字值与编码单元的数字值相等一一对应。
- 平面 1-10: 使用两个编码单元共四个字节表示一个字符,规则如下:
- 字符值减去 0x10000, 结果为 0 - 0xFFFFF 之间20位长的数字,我们暂记为 n 吧。
- 取出 n 的前10位,加上 0xD800 结果在 0xD800 - 0xDBFF 之间作为第一个编码单元,也称为前导代理(lead surrogate)。
- 取出 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编码的更多相关文章
- zzy:java采用的是16位的Unicode字符集作为编码方式------理解
java语言使用16位的Unicode字符集作为编码方式,是疯狂Java中的原话. 1,编码方式只是针对字符类型的(不包括字符串类,数值类型int等,这些只是在解释[执行]的时候放到Jvm的不同内存块 ...
- 刨根究底字符编码之十——Unicode字符集的字符编码方式CEF
Unicode字符集的字符编码方式CEF 一.字符编码方式CEF的选择 1. 由于Unicode字符集非常大,有些字符的编号(码点值)需要两个或两个以上字节来表示,而要对这样的编号进行编码,也必须使用 ...
- 刨根究底字符编码之十——Unicode字符集的编码方式以及码点、码元
Unicode字符集的编码方式以及码点.码元 一.字符编码方式CEF的选择 1. 由于Unicode字符集非常大,有些字符的编号(码点值)需要两个或两个以上字节来表示,而要对这样的编号进行编码,也必须 ...
- Unicode字符集,utf8编码,base64编码简单了解
Unicode字符集,utf8编码,base64编码简单了解 Unicode字符集,ASCII,GB2312编码集合等,类似于不同的字典,不同的字符的编码,类似于字典中的字在哪一个页哪一排. 当不同系 ...
- 多字节字符集与Unicode字符集
在计算机中字符通常并不是保存为图像,每个字符都是使用一个编码来表示的,而每个字符究竟使用哪个编码代表,要取决于使用哪个字符集(charset). 多字节字符集: 在最初的时候,Internet上只有一 ...
- Unicode规范中的BOM 和 ISO8891-1编码
Unicode规范中的BOM Unicode规范中有一个BOM的概念.BOM——Byte Order Mark,就是字节序标记.在这里找到一段关于BOM的说明: 在UCS 编码中有一个叫做" ...
- C语言:Unicode字符集
Unicode 也称为统一码.万国码:看名字就知道,Unicode 希望统一所有国家的字符编码.Unicode 于 1994 年正式公布第一个版本,现在的规模可以容纳 100 多万个符号,是一个很大的 ...
- 《windows核心编程系列》二谈谈ANSI和Unicode字符集 .
http://blog.csdn.net/ithzhang/article/details/7916732转载请注明出处!! 第二章:字符和字符串处理 使用vc编程时项目-->属性-->常 ...
- 关于Unicode字符集
最初的unicode编码是固定长度的,16位,也就是2两个字节代表一个字符,这样一共可以表示65536个字符.显然,这样要表示各种语言中所有的字符是远远不够的.Unicode4.0规范考虑到了这种情况 ...
随机推荐
- iOS RC4加解密算法
-(NSString *)encrypt:(NSString *)string withKey:(NSString *)key{ self.sBox = [[self frameSBox:key] m ...
- servlet的doPost 和doGet和web文件结构
doPost和doGet分别由 tomcat自己来决定调用post 还是get 方式查询 get:url有少量的参数信息,一般用到查询那里 (像百度.. post一般用来提交大文件数据(二进制数据 d ...
- CSS的inherit与auto使用分析
一个很显浅的寓言,千年老树,电打雷劈,屹立不倒,却毁于蝼蚁的侵袭之下.自以为精通CSS的人,常常被一些小问题搞到头晕脑胀. 通常是一个很小的数值,经过层层放大歪曲后,整个布局就走形了.CSS是一门很简 ...
- PHPCMS V9 学习总结(转)
转自:http://www.cnblogs.com/Braveliu/p/5074930.html 在实现PHPCMS网站过程中,根据业务需求,我们遇到很多问题,特此总结如下,以便大家参考学习. [1 ...
- login-登录
<!DOCTYPE html><html><head><meta charset="UTF-8"><title>Inse ...
- JS 打字机效果
请点我,查看效果 我送过你礼物 试过对你不管不顾 我挂过你电话 也曾为你哭到沙哑 我曾经为你去学做过晚餐 曾觉得你的关心太烦 也曾为你起得很早 试过狠心把你甩掉 试过偷偷拍你的微笑 也曾经把你电话删掉 ...
- PHP通过链接获取二进制数据的方法
function urltoblob($url){ $data = @file_get_contents($url); //如果file得不到数据,则给空值 if(!$data){ $data = & ...
- jQuery API中文文档
jQuery API中文文档 http://www.css88.com/jqapi-1.9/category/events/event-handler-attachment/ jQuery UI AP ...
- STM32学习笔记——定时器中断(向原子哥学习)
定时器中断 STM32 的定时器功能十分强大,有 TIME1 和 TIME8 等高级定时器,也有 TIME2~TIME5 等通用定时器,还有 TIME6 和TIME7 等基本定时器.在本章中,我们将利 ...
- find_cmd函数分析
一.概述 1.函数位置 common/command.c 2.函数功能分析 解析命令的关键环节是如何根据输入命令查找对应命令的信息,从而跳转到对应命令的函数处执行程序.这必然涉及到如何存放命令的详细信 ...