Unicode编码详解(三):UTF-8编码

Unicode编码详解(三):UTF-8编码


本文为原创文章,转载请注明出处,或注明转载自“黄邦勇帅(原名:黄勇)

本文是对《C++语法详解》一书相关章节的增补,以增强读者对字符的理解,因为《C++语法详解》引用的标准过于老旧。

《C++语法详解》网盘地址:
https://pan.baidu.com/s/1dIxLMN5b91zpJN2sZv1MNg

本文摘自本人所作《Unicode编码和双向算法(bidi)详解》网盘地址
链接:https://pan.baidu.com/s/1LLKv22jQPmeba1XUCm0xoQ?pwd=a3x8
提取码:a3x8

有兴趣的读者可参阅本人所著《C++语法详解》一书,电子工业出版社出版,该书语法示例短小精悍,对查阅C++知识点相当方便,并对语法原理进行了透彻、深入详细的讲解,可确保读者彻底弄懂C++的原理,彻底解惑C++,使其知其然更知其所以然。此书是一本全面了解C++不可多得的案头必备图书。

由于本人能力有限,文中难免有错漏之处,望广大读者指出更正,不胜感激


注意:若对本文的专业术语不了解,请参阅本系列文章(一)和(二)

1、

UTF-8编码方式是目前使用最广泛的一种Unicode编码方式,但不是最早出现的,UTF-16比UTF-8早。

2、

UTF-8使用的是8位码元的变长码元序列编码方式,说简单点就是,使用变长字节来编码(即,编码后形成的二进制串长度不是固字的)。注意,UTF-8的码元长度是固定的8位,但编码后形成的码元序列长度不是固定的。UTF-8一般使用1到4个字节编码,当然也可以更长。

3、UTF-8编码方式的算法

首字节用于区分编码的字节数,即,从首字节就能判断出编码后有多少个字节。规则为:除单字节编码以0开头外,多字节编码首字节1的个数用于判断编码后的字节长度,然后紧接着以数字0作为终结标志,除首字节外,多字节编码的后续字节以10开头,具体规则如表5所示
在这里插入图片描述

4、UTF-8编码方法

①、在表5中查找字符的码点所在的码点范围,以确定应使用几个字节编码该字符
②、将字符的码点转换为二进制
③、将转换后的二进制数值从右到左(即从最后一位低位开始)依次按相同顺序填充表5中的x,多出的x填充0。
④、示例:“汉”的Unicode的码点是U+6C49 (110 1100 0100 1001 ) ,其编码过程如下:

  • 6C49在表5的码点范围为U+0800 ~ U+FFFF,所以应使用3个字节编码
  • 将6C49的二进制数110 1100 0100 1001从最后一位开始,按从右向左的顺序填充表5中的x,最终得到“汉”字的UTF-8编码为1110 0110 1011 0001 1000
    1001(0xE6 B189),如图2所示

在这里插入图片描述

5、UTF-8解码过程

①、当读到一个字节的首位为0时,表示这是一个单字节编码的字符(即,ASCII字符)
②、当读到一个字节的首位为1时,表示这是一个多字节编码的字符,分以下两种情形

  • 情形1:若继续读到1,则表示这是首字节,然后继续读到0为止,一共读取了几个1,就表示这个字符为几个字节的编码,
  • 情形2:若紧接着读到0,则表示该字节为多字节编码的后续字节。
6、UTF-8编码方式的显著特点

①、节省存储空间

  • 由于UTF-8使用的变长字节编码,所以,可以节省存储空间,比如,一个字节的ASCII字符,就可使用一个字节来存储,其他字符则可以使用多个字节来存储。

②、扩展性好

  • UTF-8的编码空间足够大(即,编码后的二进字串足够长),可适应Unicode标准更多的字符,因此,其扩展性好

③、与ASCII编码方式完全兼容

  • ASCII字符集中的字符(码点范围为U+0000~U+007F),用一个字节表示就可以了,其编码方式与ASCII编码一致,因此,UTF-8编码方式与ASCII编码方式完全兼容。但是,扩展ASCII字符集(比如EASCII字符集)中的扩展字符需要2个字节来编码

④、无字节序

  • UTF-8编码方式已经明确了字节的顺序,因此不存在字节序的问题

⑤、字节0xFE、0xFF与字节序标记(BOM)

  • 字节0xFE和0xFF永远不会在UTF-8编码中出现,因此,可使用这两个字节作为字节序标记(BOM)来标明UTF-16或UTF-32的字节序
  • 由于UTF-8编码不存在字节序的问题,因此没必要再添加BOM(即,字节序标记),若添加了BOM,则仅用于表明该文件是由UTF-8编码方式编码的,不再用于说明字节序。
  • 事实上,为使用UTF-8编码的文件加上BOM是多此一举的事情,但是,Windows还是加上了BOM(比如,记事本就有BOM),由此造成了很多不必要的麻烦,比如Unix系统就不建议使用BOM。
  • 注意:Windows为UTF-8加的BOM的值是0xEF BB BF,而UTF-16和UTF-32是直接以0xFEFF或0xFFFE来表示是大端序还是小端序的。为什么使用的是0xEF BB
    BF呢?这是因为0xEF BB BF是把0xFEFF按UTF-8编码后所得到的二进制串。所以,当遇到以0xEF BB BF开头的文件时,则表示这是以UTF-8的方式编码的文件

⑥、自同步和非传递性

  • 自同步:由于UTF-8编码仅通过检查一个码元便可判断出当前字符的下一个字符的起始码元,每个字符的边界很明确,因此在传输过程中若有字节序列丢失,并不会造成乱码现象,或者,当存在错误的字节序列时也不会影响到其他字节的正常读取,这一性质被称为“自同步”。比如,读取了一个10xxxxxx开始的字节,但找不到首字节,则可以直接丢弃后续字节,因为它没有意义。

  • 非传递性:是指单一的UTF-8码元出错不会被传递到文本的其他部分去,仅涉入到该字符,因此,文本中某些字符数据被破坏,其影响是局部的。

  • 若文本的编码不具有自同步和非传递性,则需从头开始分析文本才能确定不同字符的码元边界,同理,若局部字符数据被破坏,则很可能被传递到整个文本,从而导致整个文本都无法正确显示。很多早期其他的字符编码方式并不具有这两个特性,如GBK、Big等。

    ⑦、不利于索引操作、计算字符数等
    由于UTF-8是变长编码的,所以,不能根据字符数量直接判断出UTF-8文本的字节数(即,文本大小),因此,计算字符数、正则表达式检索等操作的效率都不高。

7、

UTF-8是较为理想的编码方式,因此应尽量使用UTF-8,特别应尽量使用UTF-8 without BOM(即,不带BOM的UTF-8)

本文作者:黄邦勇帅(原名:黄勇)
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值