文本文件与字符编码

5 篇文章 0 订阅
4 篇文章 0 订阅

编码的本质

编码就是使用字节数据表示字符。分为数理逻辑层和展示层。前者决定了一个字符的索引值(编码值/代码点,code point),后者决定了索引值的存放/传输方式。

比如文本文件流在操作系统看来是字节流,这涉及到两个方面的问题:

1.这些字符的索引值是多少?

2.这些字节流如何被正确的解释出来?

第一个问题实际上就是字符编码的问题,在世界上,有多种编码规则,如 ASCII,UNICODE,GBK,等等,为了统一全世界各个字符的编码,即,给全世界每一个字符一个特定的编码值,这就是 UNICODE 编码。采用 UNICODE 编码规则的字符都能唯一准确地定位。UNICODE 编码只是给每个字符安排了一个值用于索引到这个字符,它不对存储和传输作出规定。

第二个问题实际上是如何规定编码值的存储方式:可以使用任意方式存储,只要该方式是可逆的,能够正确还原出编码值即可。于是就有了 UTF8,UTF16,UTF-32 这么多 UNICDOE 编码的存储方式。 

UTF8 

该名称的含义是,使用单字节(8位)作为编码单元,使用以下的方式去表示 UNICODE 编码值:

0xxxxxxx                                                                (00-7f)
110xxxxx 10xxxxxx                                                 (c0-df)(80-bf)
1110xxxx 10xxxxxx 10xxxxxx                                  (e0-ef)(80-bf)(80-bf)
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx                    (f0-f7)(80-bf)(80-bf)(80-bf)
111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx           (f8-fb)(80-bf)(80-bf)(80-bf)(80-bf)
1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx  (fc-fd)(80-bf)(80-bf)(80-bf)(80-bf)(80-bf)
这种表示方试非常科学,体现在:

1.由于是单字节编码规则,因此,无需考虑字节序的问题:低地址的字节在前,高地址的在后。

2.可变存储,节省空间:当表示的编码值小于 2^7 时,只需要一个字节,当编码值范围为[2^7 , 2^ 11) 时只需要两个字节......

3.可表示的编码值的总数量为:2^7 + 2^11 + 2^16 + 2^21 + 2^32,(根据排列组合总数得出),肯定能够表示所有的 UNICODE 编码总数。

UTF16 

含义是使用两个字节(16位)作为编码单元,它是在第一个版本的 UNICODE 编码出来后产生的编码方式,第一版本的 UNICODE (UCS-2,Universal Character Set code in 2 octets,)使用双字节表示代码点,范围是0 ` 65535,正好 UTF16 使用双字节编码,因此,它直接拿两个字节表示 UNICODE 编码值。但是这种方式有两个弊端:

1.由于编码单元是双字节,故存在字节序的问题:到底这两个字节中哪一个字节是处于高位的?

2.UTF16 由于最少使用双字节表示字符,故对于编码值小于 128 的字符使用双字节表示就浪费了一个字节。

3.UTF16 表示的字符数量明显小于 UTF8,因为 UTF16 对于任意字符都使用两字节表示,并非像 UTF8 那样变长编码。

第三点只在 UNICODE 的 UCS-2 中成立,但在第二版本的 UNICODE (UCS-4,使用四字表示代码点)可能有些武断,实际上在 UCS-4,UTF16 也是变长编码。这是为了兼顾表示更多的字符。如果不使用变长编码,两字节的 UTF16 撑死也表示不了多于 65536 个字符。下面具体看它是怎么做到的。

1.从 UTF16 的码值范围中扣出这一块:[0xD800 , 0xDFFF],称为代理区,这一部分用来表示 UCS-2 不能表示的代码点范围: [0x10000 , 0x10FFFF],称为辅助平面。设要表示的代码点二进制为 a a a a a a a a a a b b b b b b b b b b.

2.将代码点的高十位加上 0xD800,范围是 [0xD800 , 0xDBFF],低十位加上 0xDC00,范围是 [0xDC00 , 0xDFFF]。这两个区域的并正好就是代理区 [0xD800 , 0xDFFF];

3.因此对于辅助平面内的代码点,将其高十位加上 0xDC00 作为前导字,将其低十位加上 0xDFFF 作为后尾字,存储在一起(具体大端小端因需而异)。

4.以小端模式(数据低位在低地址)举例解析时,只要碰到有一个字(双字节)的值范围位于 [0xD800 , 0xDFFF] 之间,则知道当前代码点占用双字(四个字节),那么再取下一个字,一起解析出来作为代码点值。否则不位于该范围内,则说明是正常的到 UCS-2 的映射。

综上,UTF16 也是变长编码:可能是双字节,可能是四字节。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值