文件编码

从文件编码的方式来看,文件可分为ASCII码文件(文本文件)和二进制码文件(流式文件)两种。


ASCII码文件在磁盘中存放时每个字符对应一个字节,用于存放对应的ASCII码,例如,数5678的存储形式为:
ASCII码:  00110101 00110110 00110111 00111000
               ↓     ↓      ↓        ↓
十进制码:          5      6       7                8 共占用4个字节。
ASCII码文件可在屏幕上按字符显示,例如源程序文件就是ASCII文件,用DOS命令TYPE可显示文件的内容,由于是按字符显示,因此能读懂文件内容。


二进制文件是按二进制的编码方式来存放文件的,例如,数5678的存储形式为:00010110 00101110只占二个字节,二进制文件虽然也可在屏幕上显示,但其内容无法读懂,C系统在处理这些文件时,并不区分类型,都看成是字符流,按字节进行处理,输入输出字符流的开始和结束只由程序控制而不受物理符号(如回车符)的控制,因此也把这种文件称作"流式文件"。


1、big endian和little endian
big endian和little endian是CPU处理多字节数的不同方式,例如"汉"字的Unicode编码是6C49,那么写到文件里时,究竟是将6C写在前面,还是将49写在前面?如果将6C写在前面,就是big endian,如果将49写在前面,就是little endian,我们一般将endian翻译成"字节序",将big endian和little endian称作"大尾"和"小尾"。

2、字符编码、内码,顺带介绍汉字编码
字符必须编码后才能被计算机处理,计算机使用的缺省编码方式就是计算机的内码,早期的计算机使用7位的ASCII编码,为了处理汉字,程序员设计了用于简体中文的GB2312和用于繁体中文的big5。
GB2312(1980年)一共收录了7445个字符,包括6763个汉字和682个其它符号,汉字区的内码范围高字节从B0-F7,低字节从A1-FE,占用的码位是72*94=6768,其中有5个空位是D7FA-D7FE。
GB2312 支持的汉字太少,1995年的汉字扩展规范GBK1.0收录了21886个符号,它分为汉字区和图形符号区,汉字区包括21003个字符,2000年的 GB18030是取代GBK1.0的正式国家标准,该标准收录了27484个汉字,同时还收录了藏文、蒙文、维吾尔文等主要的少数民族文字,现在的PC平台必须支持GB18030,对嵌入式产品暂不作要求,所以手机、MP3一般只支持GB2312。
从ASCII、 GB2312、GBK到GB18030,这些编码方法是向下兼容的,即同一个字符在这些方案中总是有相同的编码,后面的标准支持更多的字符,在这些编码中,英文和中文可以统一地处理,区分中文编码的方法是高字节的最高位不为0,按照程序员的称呼,GB2312、GBK到GB18030都属于双字节字符集 (DBCS)。
有的中文Windows的缺省内码还是GBK,可以通过GB18030升级包升级到GB18030,不过GB18030相对GBK增加的字符,普通人是很难用到的,通常我们还是用GBK指代中文Windows内码


3、Unicode(UCS)和UTF
前面提到从ASCII、GB2312、GBK到GB18030的编码方法是向下兼容的,而Unicode只与ASCII兼容(更准确地说,是与ISO-8859-1兼容),与GB码不兼容,例如“汉”字的Unicode编码是6C49,而GB码是BABA。
Unicode 也是一种字符编码方法,不过它是由国际组织设计,可以容纳全世界所有语言文字的编码方案,Unicode的学名是"Universal Multiple-Octet Coded Character Set",简称为UCS,UCS可以看作是"Unicode Character Set"的缩写。
UCS规定了怎么用多个字节表示各种文字,怎样传输这些编码,是由UTF(UCS Transformation Format)规范规定的,常见的UTF规范包括UTF-8、UTF-7、UTF-16。


4、UTF编码
UTF-8就是以8位为单元对UCS进行编码,从UCS-2到UTF-8的编码方式如下:
UCS-2编码(16进制)     UTF-8 字节流(二进制)
0000 - 007F               0xxxxxxx
0080 - 07FF               110xxxxx 10xxxxxx
0800 - FFFF               1110xxxx 10xxxxxx 10xxxxxx
例如"汉"字的Unicode编码是6C49,6C49在0800-FFFF之间,所以肯定要用3字节模板了:1110xxxx 10xxxxxx 10xxxxxx,将6C49写成二进制是:0110 110001 001001, 用这个比特流依次代替模板中的x,得到:11100110 10110001 10001001,即E6 B1 89。
UTF-16以16位为单元对UCS进行编码,对于小于0x10000的UCS码,UTF-16编码就等于UCS码对应的16位无符号整数,对于不小于0x10000的UCS码,定义了一个算法,不过由于实际使用的UCS2,或者UCS4的BMP必然小于0x10000,所以就目前而言,可以认为UTF-16和UCS-2基本相同,但UCS-2只是一个编码方案,UTF-16却要用于实际的传输,所以就不得不考虑字节序的问题。


5、UTF的字节序和BOM
UTF-8以字节为编码单元,没有字节序的问题,UTF-16以两个字节为编码单元,在解释一个UTF-16文本前,首先要弄清楚每个编码单元的字节序,例如收到一个"奎"的Unicode编码是594E,"乙"的Unicode编码是4E59,如果我们收到UTF-16字节流"594E",那么这是"奎"还是"乙"?
Unicode规范中推荐的标记字节顺序的方法是BOM,BOM不是“Bill Of Material”的BOM表,而是Byte Order Mark,BOM是一个有点小聪明的想法:在UCS 编码中有一个叫做"ZERO WIDTH NO-BREAK SPACE"的字符,它的编码是FEFF,而FFFE在UCS中是不存在的字符,所以不应该出现在实际传输中,UCS规范建议我们在传输字节流前,先传输字符"ZERO WIDTH NO-BREAK SPACE",这样如果接收者收到FEFF,就表明这个字节流是Big-Endian的,如果收到FFFE,就表明这个字节流是Little-Endian的,因此字符"ZERO WIDTH NO-BREAK SPACE"又被称作BOM。
UTF-8不需要BOM来表明字节顺序,但可以用BOM来表明编码方式,字符"ZERO WIDTH NO-BREAK SPACE"的UTF-8编码是EF BB BF,所以如果接收者收到以EF BB BF开头的字节流,就知道这是UTF-8编码了,Windows就是使用BOM来标记文本文件的编码方式的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值