`
kanwoerzi
  • 浏览: 1646657 次
文章分类
社区版块
存档分类
最新评论

精确解释Unicode

 
阅读更多

我决心了解一下编码知识——主要是Unicode——及相关概念,搜索阅读了网上的很多文章,明白了一些,另一些却很模糊,而且有一些不同文章的描述是冲突的!我因此查阅了很多网上的资料,主要有中英文维基百科和Unicode.org,终于明白了其中的奥妙。

独乐乐不如众乐乐,我因此撰此文帮助大家最大程度地厘清UnicodeUCSUTF-8UTF-16UCS-2UCS-4之间的关系。对于网上随手可得的资料,如ASCII码表、UTF-16算法的程序代码,则不是本文重点。

网上其他文章概念模糊、说法冲突,我觉得一是上述词语本身就具有多重含义,很难把握;二可能是作者本身理解不到位,含糊了过去;三可能是那些文章缺少精确的表达方式,很容易使人误解。于是,我选择了用数学及程序代码相结合的方式,试图给予最清晰的定义。

我水平亦有限,哪里理解不到位或表达不清楚,希望读者不吝赐教。

这里格式我不修改了,嫌格式不漂亮的朋友可去https://docs.google.com/viewer?a=v&pid=explorer&chrome=true&srcid=0B92-FAjNvVzGNGQxNGI2MzctZGJlMC00YzhmLTg3MWItMGI0MWVhOTM4M2I4&hl=zh_CN获取PDF版。

基本概念

字符是文字与符号的总称,包括文字、图形符号、数学符号等。字符集是字符的集合。

(字符)编码当名词用,是一个从一指定字符集一指定集合的函数,如果用程序代码1来表示,可以写作Encoding<char t></char>

编码当动词用,是建立一个从一指定字符集一指定集合的函数。例如将汉字对应到整数(Encoding<char int></char>),将英文字母对应到可在电线中传输的电脉冲(Encoding<char></char>电脉冲模式>)。

如果字符编码特化为Encoding<char int></char>,即字符转换为整数,则成为编码字符集(函数是特殊的集合)。很多文章上说的字符集其实是编码字符集。

码点是编码字符集的上域2中的一个元素。

为了本文的叙述方便,额外定义几条表达方式。

编码字符集有以下属性:

  • 字库3ASCII的字库是英文字母+数字+其他一些符号 1

  • 编码长度4ASCII的编码长度是7个二进制位。编码长度≤表示长度 2

  • 表示长度5ASCII的表示长度是8个二进制位(最高位为0 3

编码字符集ASCII中字符A的编码数字是656 4

编码字符集ASCII中字符A的二进制流是01000001。相应地,十六进制流是41,十进制流是65。与编码数字不同,N进制流要开头补0,以达到表示长度。 5

常见的编码字符集

GB2312是简体字集,全称为GB2312(80)字集,共包括国标简体汉字6763个。

BIG5大五码是台湾繁体字集,共包括国标繁体汉字13053个。

GBK是简繁字集,包括了GB字集、BIG5字集和一些符号,共包括21003个字符。

GB18030是国家制定的一个强制性大字集标准,全称为GB18030-2000,它的推出使汉字集有了一个“大一统”的标准。

ASCII

我们知道,在计算机内部,所有的信息最终都表示为一个二进制的字符串。每一个二进制位有01两种状态,因此八个二进制位就可以组合出 256种状态,这被称为一个字节。也就是说,一个字节一共可以用来表示256种不同的状态,每一个状态对应一个符号,就是256个符号,从 000000011111111

上个世纪60年代,美国制定了一套字符编码,对英语字符与二进制位之间的关系,做了统一规定。这被称为ASCII码,一直沿用至今。

ASCII的字库包括128个字符,比如空格(SPACE)的编码数字是32,二进制流是00100000。这128个字符(包括32个不能打印出来的控制符号),只占用了一个字节的后面7位,最前面的1位统一规定为0

在电线里传输被ASCII编码的二进制流时,为了检验错误,会修改最高位,用来做奇偶校验。这利用了ASCII本身的性质(最高位都是0)。

UCS

ISO10646标准所定义的通用字符集(Universal Character Set),编码长度可达32位。

Unicode

Unicode是一种正在发展的编码字符集,由统一码联盟制定,希望将全世界常用文字都函括进去。Unicode兼容ASCII7ASCII中有的字符Unicode中都有,并且对应相同的编码数字。

Unicode编码长度可达到32位,即4字节。第一字节称为组,第二字节称为面,第三字节称为行,第四字节称为点。第0组第0面里的字符可以只用2个字节表示,且涵盖了绝大部分的常用字,所以备受青睐。为了方便称呼,Unicode给它了一个名称——基本多文种平面BMP)。基本多文种平面值域和上域都是0FFFF,共计65535个码点。8 9基本多文种平面是Unicode的子集。

虽然Unicode的表示长度是32位,但因为通常表示的是常用字,且常用字在BMP的字库里,所以表示长度往往缩减为16位。

UnicodeUCS的关系

ISO统一码联盟是两个不同的组织,最初制定了不同的标准;但后来两个组织制定的编码字符集相互兼容。10现在往往只说UnicodeUCS这个名词不常见。

转换格式

以上说的都只是编码字符集——字符到整数的函数。虽然表示长度往往是8的倍数,却没有规定二进制流应该如何放入到几个字节里去。

比如,Unicode中字符“严”的十六进制流是4E25(缩减了的表示长度),是直接保存为两个字节4E25呢,还是经过一些运算再保存呢?

读者可能觉得这个问题很无聊。我们已经知道,英文字母只用一个字节表示就够了,如果每个符号用两个或四个字节表示,那么每个英文字母前都必然有二到四个字节是0,这对于存储来说是极大的浪费,文本文件的大小会因此大出二三倍,这是无法接受的。

UTF正是为了解决这个问题而诞生的。UTF全称为Unicode Translation FormatUnicode转换格式)。

转换格式是一个从二进制流集合字节数组的集合的函数,可以写作Encoding<binary byte></binary>。又二进制流可以计算为数字,转换格式可以写作Encoding<int byte></int>

UTF-8

UTF-8是一种变长转换格式。它使用1~4个字节表示一个符号,根据不同的二进制流而改变字节长度。

UTF-8的规则很简单,只有二条:

  • 对于单字节的符号,字节的第一位设为0,后面7位为这个符号的Unicode码。因此对于同一个英语字母在UTF-8下和在ASCII码下的像11是相同的。

  • 对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的二进制位用来从后往前放置这个符号的二进制流。

下表总结了编码规则,字母x表示用来放置二进制码的位置。

Unicode码点

像(二进制)

0000 0000 - 0000 007F

0xxxxxxx

0000 0080 - 0000 07FF

110xxxxx 10xxxxxx

0000 0800 - 0000 FFFF

1110xxxx 10xxxxxx 10xxxxxx

0001 0000 - 0010 FFFF

11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

UTF-16

UTF-16的编码方法12是:

  • 如果二进制流b小于0x10000,也就是十进制的065535之内,则直接使用两字节表示。

  • 如果二进制流b大于等于0x10000,将b-0x10000的结果中的前 10 位作为高位和0xD800进行逻辑或操作,将后10 bit作为低位和0xDC00逻辑或操作,这样组成的4个字节就构成了b的编码。

举个例子。假设要算(U+2A6A5,四个繁体字龙)13UTF-16下的像,因为它超过 U+FFFF,所以 2A6A5-10000=0x1A6A5=

100001 1010 01 | 0xD800 = 0xD896

1010 1010 0101 | 0xDC00 = 0xDEA5

所以U+ 2A6A5 UTF-16中的像是D8 96 DE A5

UCS-2

UCS-2ISO制定的,用来转换UCS的。但既然UnicodeUCS相互兼容,便也可以用来转换Unicode

UCS-2基本多文种平面的值域两个成员的字节数组的集合的函数,即每个BMP码点都通过前面补0的方式固定地用两个字节表示。记得因为代理区的存在,一个码点并不代表一个字符。

UCS-2UTF-16的子集,因为UTF-16额外规定了BMP以外的字节表示。

UCS-4

UCS-4ISO制定的,用来转换UCS的。但既然UnicodeUCS相互兼容,便也可以用来转换Unicode

UCS-4Unicode中的头128组的值域四个成员的字节数组的集合的函数,即每个码点都通过前面补0的方式固定地用四个字节表示。四个字节的范围是07FFFFFFF,即31个二进制位。

UTF-32

但是,ISO/IEC 10646已经宣布,今后所有的字符都将分配在10FFFF (即第0组头17个平面)以内,所以UCS-47FFFFFFF上限没有意义。14所以制定了UTF-32

UTF-32Unicode中第0组头17个平面的值域四个成员的字节数组的集合的函数,即每个Unicode码点都通过前面补0的方式固定地用四个字节表示。

可见,UTF-32UCS-4的子集,UCS-4包含UTF-3215UCS-4已经没有使用的意义。

小结

转换格式

定义域

值域

UTF-8

0-10 FFFF

0组头17平面的值域

1-4字节

UTF-16

0-10FFFF

0组头17平面的值域

24字节

UCS-2

0-FFFF

基本多文种平面的值域

2字节

UCS-4

0-7FFFFFFF

128组的值域

4字节

UTF-32

0-10 FFFF

0组头17平面的值域

4字节

* 缩进代表包含关系。

现在若有软件声称自己支持UCS-2,那其实是暗指它不能支持在UTF-16中超过2字节的符号。16

字节存储的顺序

一个字符,通过Unicode,得到了二进制流;二进制流通过转换格式,得到了几个字节。那么这几个字节是由低位到高位(即低位在前)写入硬盘呢,还是由高位到低位(即高位在前)写入硬盘呢?这就是字节存储的顺序问题,即字节序问题。

为什么不统一地都由低位到高位或由高位到低位呢?因为设备执行不同的任务时,这两种方式的性能有差别。为了最大地提升性能,设备的硬件实现根据其最常做的任务决定了字节序。

Unicode规范中用字节序标记字符BOM)来标识字节序,它的编码是FEFF。这样如果接收者收到FEFF,就表明这个字节流是高位在前的;如果收到FFFE,就表明这个字节流是低位在前的。

这里相当于有一个从byte[]BOMbyte[]的字节序函数(b(byte[],bom):byte[]),给定几个字节和字节序,该函数就能算出这几个字节存往硬盘的顺序。

至此,计算机屏幕上显示的字符保存到硬盘上的过程已经清晰了:

对该字符c应用编码字符集,结果为n

Encoding<char int>(c) → n</char>

对整数n应用转换格式,结果为。

Encoding<int byte>(n) → bytes</int>

对应用字节序函数,结果为硬盘上的字节数组。

b(bytes,bom) → bytesInDisk

UTF-8有严格的字节顺序,不需要BOM。但如果在字节流前面加上BOMUTF-8下的像EF BB BF,接收者一收到就知道这是UTF-8编码。所以用UTF-8格式存储,仍然会往文件头写EF BB BF,以表明其转换方法。

UTF-16UCS-2UCS-4UTF-32都没有严格的顺序,所以需要借助BOM

复合函数

数学上的复合函数是一个函数。若g(x)f(x)是函数,则g(f(x))是复合函数。

编码字符集ASCII因为不需要转换格式17、没有字节序的问题,所以ASCII又是:

  • 编码字符集ASCII与转换格式的复合函数(转换格式不作任何事)

  • 编码字符集ASCII、转换格式与字节序函数的复合函数(转换格式和字节序函数不作任何事)

UTF-8第一条规则用的就是上面的第一个含义。

UTF-16BEUTF-16LE,是转换格式UTF-16与高位在前或低位在前的复合。UTF-16BE有时缩写为UTF-16,注意,这与转换格式UTF-16是不同的!18

UCS-2BEUCS-2LE,是转换格式UCS-2与高位在前或低位在前的复合。UCS-2BE有时缩写为UCS-2。注意,这与转换格式UCS-2是不同的!3

UCS-4BEUCS-4LE,是转换格式UCS-4与高位在前或低位在前的复合。UCS-4BE有时缩写为UCS-4。注意,这与转换格式UCS-4是不同的!3

UTF-32BEUTF-32LE,是转换格式UTF-32与高位在前或低位在前的复合。UTF-32BE有时缩写为UTF-32。注意,这与转换格式UTF-32是不同的!19

名称

编码次序

字节存储顺序

BOM

UTF-16LE

低位在前

31 67

2C 00

7F 80

69 D8 A5 DE

UTF-16BE

高位在前

67 31

00 2C

80 7F

D8 69 DE A5

UTF-16

低位在前,包含BOM

FF FE

31 67

2C 00

7F 80

69 D8 A5 DE

UTF-16

高位在前,包含BOM

FE FF

67 31

00 2C

80 7F

D8 69 DE A5

Windows记事本中的编码

我们在Windows系统中保存文本文件时通常可以选择编码为ANSIUnicodeUnicode big endianUTF-8。已知Unicode是编码字符集,big endian是一种字节序,UTF-8是转换格式。这三种不同的东西放在一起,是什么意思呢?答案是复合函数。

请看实验!我将字符用这四种选项分别保存,然后查看其16进制代码。记得这个字的二进制流是2A6A5,在UTF-16中的像是D8 96 DE A5。读者可以练习一下计算2A6A5UTF-8下的像。



选项

编码字符集

转换格式

字节存储的顺序

ANSI

英文文件:ASCII

直接表示

直接存储

简体中文系统:GB2312

繁体中文系统:Big5

Unicode

Unicode

UTF-16

低位在前

Unicode big endian

Unicode

UTF-16

高位在前

UTF-8

Unicode

UTF-8

直接存储

所以,以上四项都是复合函数,复合了编码字符集、二进制的字节表示和字节存储的顺序。

很多软件和文章中提到的UnicodeUTF-8之类的,都是这种复合。

爱让一切都对了

<sdfield sdnum="2052;2052;YYYY" type="DATETIME"><font face="Times New Roman, serif"><font style="font-size: 12pt">2011</font></font><font style="font-size: 12pt"><font face="宋体">年3月21</font><font face="Times New Roman, serif">3月21日 </font><font face="宋体">月21日 星期</font><font face="Times New Roman, serif">21日 星期一</font><font face="宋体">日 星期一</font></font></sdfield>

本文依照知识共享- 署名-相同方式共享3.0协议发表


image

四个繁体字龙

1C#语法,依据.Net Framework 4.0

2编码字符集是函数,函数有值域。值域是上域的子集。Unicode中有些位置是保留区域,没有字符来对应,所以不属于值域,但属于上域。

3即函数的定义域。

4即值域的基数的二进制表示的位数。

5即上域的基数的二进制表示的位数。

6即字符A在编码字符集ASCII中的像是01000001

8基本多文种平面里有个代理区,仅该区就可表达1048576个字符。

11UTF-16看成函数。设有函数f,则xf下的是f(x)。若f(x)=2x+1,则3f下的像是。

13文末有该字的图片。

17作动词用。不同于上文的名词转换格式

18根据Vim FencView插件。

19这是我的推理。

分享到:
评论

相关推荐

    让开源项目TinyXml支持Unicode(wchar_t)

    而在另外一个编码标准库下不存在,这时精确的相互转换就无法执行,但是仍然有默认字符转换。 -- 6. VC语言,当定义了宏 _UNICODE 后,_T系列宏或函数,以`宽字符`承载UTF16编码。 TinyXml如何提供`宽字符`函数...

    最小的UNICODE文件

    生成编码文件的控制台程序。 运行后,编码保存在"D:\unicode.txt" 【精确度低-许多外国字都不能显示】 网速不给力,且只需要中文和英文部分的可以用这个。 汉字主要部分是从4E00开始的。

    分子量计算器 6.6.0

    * 程序全面支持UNICODE - RTF格式历史记录合并到“历史记录”中,原RTF格式历史记录选项不再有效 - 修正一个前端显示时主窗口可能遮住对话窗口的BUG 6.4.1 + 增加批量计算功能,在“工具”菜单中,一些过长...

    使用python绘制雷达图

    plt.rcParams["axes.unicode_minus"] = False # 解决保存图像是负号"-"显示为方块的问题 plt.style.use("ggplot") # 设置ggplot样式 # 原始数据集并获取数据集长度 results = [{"准确率": 0.91, "精确率": 0.82, ...

    开卷有益(手机读书软件)

    开卷有益说明支持ANSI(常规格式),UTF8,Unicode 16L,Unicode 16B四种编码格式的TXT文件和UMD文件.支持点击,拖拽,滑动翻页等多种阅读方式.支持全屏,横屏,竖屏和重力感应等多种屏幕方式.支持逐页,逐行,像素和无限等多种...

    wcwidth:Python库,用于测量呈现给终端的unicode字符串的宽度

    解决方案:符合POSIX.1-2001和POSIX.1-2008的系统提供和 C函数,此python模块的函数精确复制了这些函数。 这些函数返回一个unicode字符串预期占用的单元数。 安装 该软件包的稳定版本在pypi上维护,请使用pip安装:...

    PC端微信清理工具,数据恢复

    1、支持Windows全系统(32/64位),支持Unicode编码(识别多语言、各类乱码文件); 2、多线程运行,使用过程丝滑般流畅; 3、智能区分微信账号,多个账号可分开清理; 4、分析占用数据占比,自定义清理数据范围...

    pdf转换成word

    想把PDF文件里的好东西复制下来是一件很让人头疼的问题,现在有了这款PDF转DOC文档工具,问题就迎刃而解了...转换速度快,精确,易于使用,支持unicode和亚洲字体编码,无需安装MicrosoftWord,AcrobatReader,非常方便

    【黑莓】豆豆阅读器v0.8.0

    应用名: 豆豆阅读器(BeanReader) 适用平台: BlackBerry(JDE4.2.0版本之后) 版本: v0.8.0 (第一个发布版本) ... 精确跳转功能(百分比跳转,精确到小数点后2位)  双重进度显示(进度条,百分比)

    WinHex

    * 精确的驱动器盘符写入保护(默认启用)。 * 自动保护容器选项。 * 目录浏览器选项现在允许锁定左边的列。 * 在目录浏览器上下文菜单中禁用排序的能力。 * 所有信息容器的文本可以记录到 ...

    信息技术习题(答案).doc

    A.GB2312-80是我国颁布最早的汉字编码字符集标准,它包含6000多个汉字 B.UCS- 2(Unicode)编码标准,西文字符采用单字节编码,汉字用双字节或四字节编码 C.汉字扩展内码规范(GBK)保持与GB2312-80字符集的...

    BurnAware Pro v12.3.zip

    DVD-视频,音频CD或标准数据光盘的精确副本。 其它功能: 删除或格式化可重写光盘。 检查光盘读取错误。 从损坏的光盘中提取文件。 Multiburn ISO映像文件同时写入到多台刻录机 BurnAware Pro截图

    Ollydbg2.01(alpha4)汉化版

    Ollydbg2.01(alpha4)是一个...搜索不精确的命令和摸糊的二进制序列 搜索整个分配的内存 查找引用常量或地址范围 审查和修改内存,设置断点和暂停运行方案 组装成二进制形式的最短的命令 从软盘启动 很多,很多!

    rofimoji:rofi的表情符号和角色选择器:beaming_face_with_smiling_eyes:

    不用担心,此脚本使用了来精确呈现您一直想要的选择器。 直接插入所选表情符号,或将其复制到剪贴板。 您也可以使用它来选择有人进入Unicode的任何奇怪字符。看起来如何?用法单机版运行rofimoji.py 搜索您想要的...

    Ollydbg2.01简繁中文版.

    32位汇编级调试器Ollydbg...搜索不精确的命令和摸糊的二进制序列 搜索整个分配的内存 查找引用常量或地址范围 审查和修改内存,设置断点和暂停运行方案 组装成二进制形式的最短的命令 从软盘启动 很多,很多!

    PDF To Word RTF

    款非常有用的PDF转换工具,可以快速的将PDF文档转换为Word RTF文件,允许你保留全部特性包括文字、图片、表格、链接等,同时也支持批量转换。转换速度快,精确,易于使用,支持unicode和亚洲字体编码。

    免费的swf转换格式工具

    Free SWF Converter转换SWF为AVI、XVID、DIVX、MS-MPEG4、MPEG1、MPEG2及VCD/SVCD/DVD兼容的MPEG文件时会保持非常好的图片和音频质量,不会出现丢帧情况,精确同步视频和音频。 Free SWF Converter也提供了非常详细...

    Python图像处理之图片文字识别功能(OCR)

    OCR与Tesseract介绍 将图片翻译成文字一般被称为光学文字识别(Optical Character Recognition,OCR)。...它可以通过训练识别出任何字体(只要这些字体的风格保持不变就可以),也可以识别出任何Unicode

    好用的PDF转word工具

    E­PDF PDF To Word Converter是一款非常有用的PDF转换工具,可以快速的将PDF文档转换为Word RTF文件,能保留全部特性包括文字、图片、表格、链接等,同时也...转换速度快,精确,易于使用,支持unicode和亚洲字体编码

    pdf2word[注册版],将PDF文档转换成WORD文档

    一款非常有用的pdf转换成word软件,可以快速的将PDF文档转换为Word RTF文件,E-PDF PDF To Word Converter允许你保留全部特性包括文字、图片、表格、链接等...转换速度快,精确,易于使用,支持unicode和亚洲字体编码。

Global site tag (gtag.js) - Google Analytics