C++杂谈之关于文件操作的若干问题

原文地址

http://blog.csdn.net/plzhou/article/details/20486305




C++杂谈之关于文件操作的若干问题


一、文本文件和二进制文件

      (1)文件只是计算机内存中二进制表示的数据在外部存储介质上的另一种存放方式。文件通常可以分为二进制文件和文本文件。

      (2)将数据存储在文件中时,可以将其存储为文本格式或二进制格式。文本格式是指将所有内容(甚至数字)都存储为文本。例如,以文本格式存储-2.324216e+07时,将存储该数字包含的13个字符,这需要将浮点数的计算机内部表示转换为字符,这正是<<插入操作符完成的工作。另一方面,二进制格式指的是存储值的计算机内部表示。也就是说,计算机不是存储字符,而是存储这个值的64位double表示。

      (3)对于字符来说,二进制表示和文本表示都是一样的,即字符的ASCII码的二进制表示。

      (4)对于数字来说,二进制表示和文本表示有着很大的差别。

      (5)使用二进制文件模式时,程序将数据从内存传输给文件(反之亦然)时,将不会发生任何隐藏的转换,而默认的文本模式并非如此。


二、文本方式和二进制方式

      (1)当按照文本方式向文件中写入数据时,一旦遇到“换行”字符(ASCII码为10),则会转换为“回车——换行”(ASCII码分别为13、10)。在读取文件时,一旦遇到“回车——换行”的组合(连续的ASCII码为13、10),则会转换为换行字符(ASCII码为10)。

      (2)当按照二进制方式向文件中写入数据时,则会将数据在内存中的存储形式原样输出到文件中。

      (3)由于文本方式和二进制方式在读取和写入数据时的差异,所以在写入和读取文件时要保持一致。如果采用文本方式写入,应采用文本方式读取;如果采用二进制方式写入数据,在读取时也应采用二进制方式。否则就会出现问题。

      (4)不管是文本文件还是而二进制文件,如果统一采用二进制方式进行写入和读取,则是不会出错的。因为这种读取和写入时严格按照一个字节一个字节进行的。

      注:读者一定要注意文本文件和二进制文件,文本方式和二进制方式之间的区别,不要混淆。不管是文本文件还是二进制文件,都可以采用二进制方式或文本方式打开,然后进行写入或读取。但是,对于二进制文件来说,如果以文本方式读取时,可能出现一些问题。

      文本文件和二进制文件,文本方式和二进制方式之间是没有关系的,他们描述了文件的不同方面。前者描述了文件的存储方式,后者描述了文件的打开方式(换行符有区别)。


三、格式化操作和非格式化操作

 

C

C++

格式化操作

实现函数:fscanf , fprintf,sscanf,sprintf

实现方式:利用格式字符串进行相应格式的转换

实现函数:<< , >>

实现方式:是通过对插入和提取运算符的重载实现的

读取时(数值):将字符串转换成数值

写入时(数值):经数值转化为字符串形式

非格式化操作

实现函数:fread , fwrite

实现方式:以二进制方式直接写入一定字节长度的数据

实现函数:.read ,  .write

实现方式:以二进制方式直接写入一定字节长度的数据

读取写入:数值和字符串时都不会进行任何的转换

        格式化操作和非格式化操作主要区别在于对读取写入数据的操作,前者会对数据进行相应的格式化,而后者原样输入(只是相对来说,其实是有变化的,如果内存单元式char类型,则不会变化,若是short,int等类型,则会进行相应的变化,具体如下说明)。 

 

注:关于fread、fwrite和.read、.write的说明:

      (1)(在intel系统中,最低位在前,最高位在后),当使用fwrite,.write写入数据时,char类型直接写入,short,int,long类型在会倒置,即最低位在前,最高位在后。例如:十六进制:00 01 00 00 (即:00 00 01 00 也就是2的8次方 ),十进制:256. 

      当使用fread,.read读取数据时,char类型直接读入,short,int,long类型会将文件中的数据倒置,恢复到正常的顺序(是写入的逆过程),以便正确的读入数据。

      (2)fread(const void* buf,int size,int count,FILE* file)

                fwrite(const void*buf,int size,int count,FILE* file)

      按照上述规则进行读取写入数据,读写数据大小为size*count。当分配的内存为结构体或者数组时,只要读写的数据长度正确,则函数会根据数据中具体的元素的数据类型应用上述规则。

      总结:如果内存单元式char类型,则不会变化,若是shortint等类型,则会进行相应的变化,(造成的原因:IntelMorola系统的存储方式区别:Little EndianBig Indian)

      (1)读取示例

            十六进制: 00 01 00 02 0003

            读取函数:

            short buf[3];

            fread((const void*)buf,2,3,fp);

            for(int i=0;i<3;i++)

            cout<<buf[i]<<endl;

            则显示结果为:256,512,768

      (2)写入示例

            struct test{char a;shot b;intc;long d}

            test data={‘a’,1,2,3};

            fwrite((constvoid*)&data,1,sizeof(data),fp)

            则文件的十六进制显示为:61 01 00 02 00 00 00 03 00 00 00


四、文本文件,二进制文件中的格式化、非格式化操作

 

操作

实现

文本文件

读写数值:

(可以通过格式     化和非格式化实现)

格式化操作:fscanf,fprint;<<,>>

将字符串形式的数值直接转化为相应的数据类型的数据,读取长度:从第一个非空格开始直到与数字不相同的字符为止

示例:文件中有:1234.5678

C:

double val;

fscanf(fp,”%lf”,&val);

C++:

double val;

fp>>val;

非格式化操作:fread,fprint; .read, .write(注意上述说明,最好采用char元素内存,则不会存在变化)

首先先将文件中的数值以字符串的形式完整读入,然后再将字符串转换成相应数据类型的数据,读取长度:自己指定

示例:文件中有:1234.5678

char buf[9];

fread(buf,1,8,fp);

double val;

sscanf(buf,”%lf”,&val);

读取字符串:

格式化操作和非格式化操作都是相同的,不会对字符串进行相应的转化,一般使用fgets,.gets读取字符串,主要是可以指定读取长度。直接用>>,将读入全部,因为文本文件都是字符串。

二进制文件

读取数值:

由于存储时直接存储数值的二进制形式,所以不需要进行相应的转化,只需知道数据的格式。

只能通过非格式化操作实现

读取字符串:

文件直接存储字符串的ASCII码值得二进制形式,所以直接读取一定长度的字符串即可。

      文本文件和二进制文件,文本方式和二进制方式,以及格式化操作和非格式化操作之间是没有严格的关系的,他们描述了文件的不同方面。前者描述了文件的存储方式,中间者描述了文件的打开方式,而后者描述了在对文件读取写入数据时对数据(尤其是数值)的处理方式。

  


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章