文本文件和二进制文件的区别详解

来源:互联网 发布:方正国际软件招聘 编辑:程序博客网 时间:2024/05/16 17:02

本文章结合几篇文章,加上自己的理解和实验完成。

其实,从本质上来说,所有文件都是二进制文件,也就是用0101这种形式存储。文本文件是特殊的二进制文件,我也称它为字节文件。将要存储的东西利用ASCII编码,然后存储到文件中,例如ABCD存储为01000000_01000001_01000010_01000011"(下划线''_'',是我为了增强可读性,而手动添加的),而5678存储为00110101_00110110_00110111_00111000,这两个例子都是将要存储的字符翻译成ASCII码值,然后存储到文件。而二进制文件则是根据值编码,例如我要存储5678,编程经验告诉我们,一个int值就能表示5678,00000000_00000000_00010110_00101110,这是一个int的表示形式,那就将这个存到二进制文件中去。这就是文本文件和二进制文件的区别,不难,如果二进制文件存储ABCD呢,那么也是ASCII码值存储到文件中。

下面,引用一个网友的例子。来证明。

struct Student {    int num;    char name[20];    float score;};
//使用二进制写入void write_to_binary_file(){    struct Student stdu;    stdu.num = 111;    sprintf_s(stdu.name,20,"%s","shine");    stdu.score = 80.0f;    fstream binary_file("test1.dat",ios::out|ios::binary|ios::app); //此处省略文件是否打开失败的判断    binary_file.write((char *)&stdu,sizeof(struct Student));//二进制写入的方式    binary_file.close();} //文本格式写入void write_to_text_file(){    struct Student stdu;    stdu.num = 111;    sprintf_s(stdu.name,20,"%s","shine");    stdu.score = 80.0f;    FILE *fp = fopen("test2.dat","a+");   //此处省略文件是否打开失败的判断    fprintf(fp,"%d%s%f",stdu.num,stdu.name,stdu.score); //将数据转换成字符串(字符串的格式可以自己定义)    fclose(fp);} //MAIN函数调用前面两个方法int _tmain(int argc, _TCHAR* argv[]){    write_to_binary_file();    write_to_text_file();        return 0;}

上面代码的意思是相同的一份struct类型分别用写入文本文件和二进制文件。

这个struct是{111,"shine",80.00000};

然后分布把这两个文件打开(用UltraEdit打开),然后以十六进制方式查看文件:结果如图

二进制文件:

6F 00 00 00这其实是111,一个int型4个字节,没错,然后,为什么6F其实就等于111,为什么在前面呢?因为跟大小端存储有关,Windows是小端存储,即低字节段存储在低地址,而存储是从低地址开始存储的,所以6F先存储,后面依次是高地址。

文本文件


文本文件比较好理解:1的ASCII是31(十六进制),73 68 69 6E 65是shine的ASCII,后面就是80.00000的ASCII。

至此这个实验很好的讲解了二进制文件和文本文件的区别了。

最后讲解一个比较细节的东西。

简单说就是回车换行操作,以二进制文件打开是"\r\n",以文本文件打开是"\n"。

实验结果如下:我们新建了test.txt,文件内容:


若以二进制文件打开则是如下图:


0D 0A就是回车换行了,即"\r\n",那上上图也没表面,以文本文件打开,回车换行是"\n"啊?对,问的好,以文本文件形式打开,确实看不出来,只能通过程序显示出来。

#include<iostream>#include<string>#include<fstream>#include<locale>#include<strstream>#include<stdio.h>#include<sstream>using namespace std;int main(){string *s=new string[2];char *c=new char[100];string tmp="\n";ifstream in("test.txt");{for(int i=0;i<2;i++){in.getline(c,100,'d');s[i]=c;}}in.close();const char *cc;cc=s[1].c_str();cout<<(int)cc[0]<<endl;return 0;}

运行结果:


因为上面s[1]=“回车”+1234,然后我把s[1]赋值给字符数组型的的cc,然后我输出cc[0],即输出回车的第一个字符,显示的是10(十进制),就是0A(十六进制),那你怎么知道cc[1]不是0D呢,因为Windows下的回车一般是"\r\n",即0D 0A,所以cc[0]输出了0D,即'\n',那么就证明我们的猜想了。



综上,C的文本方读写与二进制读写的差别仅仅体现在回车换行符的处理上.文本方式写时,每遇到一个''\n''(0AH换行符),它将其换成''\r\n''(0D 0AH,回车换行),然后再写入文件;当文本读取时,它每遇到一个''\r\n''将其反变化为''\n'',然后送到读缓冲区.正因为文本方式有''\n''--''\r\n''之间的转换,其存在转换耗时.二进制读写时,其不存在任何转换,直接将写缓冲区中数据写入文件.
    总地来说,从编程的角度来说,C中文本或二进制读写都是缓冲区与文件中二进制流的交互,只是文本读写时有回车换行的转换.所以当写缓冲区中无换行符''\n''(0AH),文本写与二进制写的结果是一样的,同理,当文件中不存在''\r\n''(0DH0AH)时,文本读与二进制读的结果一样.

容易发生的错误:以文本文件写文件,再以二进制方式读,每行多一个0D;反之以二进制方式写文件,以文本方式读文件,不会出错,这是区别,可以用UltraEdit进行转换。

原创粉丝点击