【转】文本文件和二进制文件的区别

一般的编程书在文件一章的开头就会告诉我们:文件分为文本文件和二进制文件两种。

大部分人就这么接受了。但也不乏有爱刨根问底的主,会抛出灵魂一问:计算机不都是用0-1的二进制来存储东西吗?为什么还有文本文件之说?文本文件难道最后不存储为二进制吗?

刚学编程的很多同学都搞不清楚这个问题。文本文件最后当然也存储为二进制,那它和二进制文件到底有什么区别?或者说计算机又怎么来区分文本文件和二进制文件呢?

其实文本文件和二进制文件的区别不在于两者的物理存储,而是在于两者对所存储二进制数的逻辑解释上。

所谓文本文件,也就是文件存储的是我们人类可读的一个个字符,比如"hello", "你好”等。当然,最后也是以二进制的方式存储在计算机上。为了把字符表示成二进制,事先得有一个所谓的码表,给出了每个字符与二进制数的对应关系,比如著名的ASCII码表。

在这里插入图片描述
当然,由于ASCII码表只能编码128个字符,完全不能满足全球那么多种不同语言的海量字符。因此,各国和机构都制定了各自不同的编码标准,颇有点多国混战的意思。这些码表有些是互相冲突的,不同国家或机构的不同字符,可能对应了同一个数字编码。

为了一统江湖,大名鼎鼎的unicode登场了,它将所有人类可读的字符都统一在了一个编码系统里。Unicode本身包括字符集和编码方案两个维度:一方面,要为每个字符指定一个数字编号;另一方面,要把这个字符对应的数字编号编码为二进制表示。

将数字编号表示成二进制不就是二进制表示了吗?为什么还有后面这一出?这是因为,由于全球的字符实在太多,超过了16位二进制能表示的数量范围(0~65535),想想仅《康熙字典》就收录了近5万汉字。当然,比如我们用32位可以表示2^32(大约为40亿)个字符,是绝对够用了。但这是不是代表每个字符都要用4个字节来编码呢?这样不是浪费了宝贵的存储空间吗?本来hello只要用5个字节就可以了,现在每个字符用32位来表示,那就要20个字节。太浪费了!

于是,就有了类似于utf-8这种可变长的编码方案。这种编码方案可以将不同的字符编码为不同的长度。这个想法其实很自然。常用的字符,我们完全可以给他们赋予更小的数字编号,从而用更少的字节数来编码,而不常用的字符,则可以用更多的字节数来编码。

好了,所以,文本文件的处理基本就是这样。你的任务是要把一段文本存储成一个文件。首先得有一个码表,指定了字符集中的每个字符对应的数字编号,然后有一个编码方案,把这个数字编号编码为一个或几个字节。对一段文本中的每个字符都执行这一操作就把这段文本转换成了一个文本文件。读取文本文件则是反向操作。首先从文件中读一个或几个字节,根据它的二进制值计算出数字编号,然后用数字编号去查码表,就得到了对应的字符,一直重复这一过程直到文件结束就行。

那二进制文件呢?

除了用上面这种方式存储的文件,其余文件都应该被理解为二进制文件。有人说二进制文件其实就是存储的二进制数,这个不完全正确。因为本质上文件都是存储的二进制数。比如65表示成二进制数为01000001,如果是文本文件,那查ASCII码表,则是大写字母’A‘,但如果不是文本文件,它就是二进制的01000001,至于说到底代表什么含义,则是创建这个文件的用户自定义的。它可以是一个二进制的整数值,也可以是某个指令的编号,或者是某个内存地址的一部分。

那到底怎么区分文本文件和二进制文件呢?

有人说根据文件的扩展名区分,这其实是一厢情愿。这就好比指望通过一个人所穿的衣服来区分男人和女人一样不靠谱。有些女人喜欢女扮男装,而有些男人也好穿裙子,更有一些人穿的是中性服装,完全看不出男女。扩展名完全可以人为地修改,而且有些文件压根就没有扩展名,因此通过扩展名区分文件是文本文件还是二进制文件是不可靠的。

那有没有完全可靠的方法来区分文本文件和二进制文件呢?

很遗憾,严格意义上来说,不存在!哦,也不对,只能说是对文件创建者之外的人或机器来说,不存在。唯一知道能完全确定文件是文本文件还是二进制文件的就是文件创建者。

比如有一个文件,它的内容是:

01001000 01000101 01001100 01001100 01001111

如果按照ASCII文本文件来解析,那么是HELLO。

但谁说它一定要是ASCII文件呢,或许我就是存了一个32位的整数1212501068外加一个字符O呢?又或者,我是存了一个RGB的三元组<72,69,76>外加一个短整型整数19535呢?再或者,我是存放的一条指令呢?比如01001000编码了JUMP这条指令,而后面的4个字节是一个地址。

那是不是就完全放弃呢?也不是。

通常在这种任务里我们不要求严格意义上的可判别。通过分析二进制内容的特征实现概率上的可判别也可以接受。比如,如果这个人有喉结,那么大概率是男人。

所以一种做法是按照文本文件的编码来分析整个文件,如果每个都可以通过查码表找到对应的字符,那么大概率是文本文件。但是,这个工作量有点大。

另一种做法基于下面一个现实:文本文件一般很少有NULL(00)字符,而一般的二进制文件(比如图像文件)包含许多值为00的字节。这一点可以作为区分文本和二进制文件的有效方法。比如,下面给出了一个文本文件、一个图片文件和一个可执行文件(后两者都是二进制文件)前一部分内容字节的16进制值。

  • 某源文件的文本文件:
    某源文件的文本文件
  • 某JPG图片
    某JPG图片
  • 某EXE文件
    某EXE文件
    当然,有些二进制文件格式会包含所谓的magic number, 这种会有助于判断文件是否为二进制文件。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值