「C语言」文件的概念与简单数据流的读写函数

    写完「C语言」单链表/双向链表的建立/遍历/插入/删除 后,如何将内存中的链表信息及时的保存到文件中,又能够及时的从文件中读取出来进行处理,便需要用到”文件“的相关知识点进行文件的输入、输出。

    其实,就算不懂得链表,也完全可以学习”文件“相关知识点,但在此之前最好有”指针“基础。

    本篇文章整理自《C语言程序设计教程--人民邮电出版社》第十二章——文件,以作文件探讨。

 

一、数据流与文件概念

二、文件的打开与关闭

三、文件的顺序读写

四、文件的随机读写

五、出错检查

六、低级I/O函数与标准I/O函数

 

一、数据流与文件概念

    1.数据流

    数据的输入与输出都必须通过计算机的外围设备,不同的外围设备对于数据输入与输出的格式和方法有不同的处理方式,这就增加了编写文件访问程序的困难程度,而且很容易产生外围设备彼此不兼容的问题。数据流(Data Stream)用来解决这个问题。

    数据流将整个文件内的数据看作一串连续的字符(字节),而没有记录的限制。

    数据流借助文件指针的移动来访问数据,文件指针目前所指的位置即是要处理的数据,经过访问后文件指针会自动向后移动。

    每个数据文件后面都有一个文件结束符号(EOF),用来告知该数据文件到此结束,若文件指针指到EOF便表示数据已访问完毕。

    2.文件

    “文件”是指存放在外部存储介质(可以是磁盘、光盘、磁带等)上的数据集合。操作系统对外部介质上的数据是以文件形式进行管理的。当打开一个文件或者创建一个新文件时,一个数据流和一个外部文件(可能是一个物理设备)相关联。

    C语言支持的是流式文件,即前面提到的数据流,它把文件看作一个字节序列,以字节为单位进行访问,没有记录界限,即数据的输入和输出的开始和结束仅受程序控制,而不受物理符号(如回车换行符)控制。

    可以从不同角度对文件进行分类

        (1)根据文件依附的性质——普通文件和设备文件。

        (2)根据文件的组织形式——顺序读写文件和随机读写文件。

        (3)根据文件的存储形式——ASCII码文件和二进制文件。

            ASCII码文件和二进制文件的主要区别:

                (1)存储形式:ASCII文件将该数据类型转换为可在屏幕上显示的形式存储,二进制文件是按该数据类型在内存中的存储形式存储的。

                (2)存储空间:ASCII所占空间较多,而且所占空间大小与数值大小有关。

                (3)读写时间:二进制文件读写时需要转换,造成存取速度较慢。ASCII码文件则不需要。

                (4)作用:ASCII码文件通常用于存放输入数据及程序的最终结果。二进制文件则不能显示出来,用于暂存程序的中间结果。

    在C语言中,标准输入设备和标准输出设备是作为ASCII码文件处理的,它们分别称为标准输入文件和标准输出文件。

    文件和内存的交互处理:

        

 

二、文件的打开与关闭

    要打开指定的文件可使用fopen()函数

        FILE *fopen(char *filename,char *mode);

    其中第二个参数mode用来设定要打开的文件类型和指定文件的访问模式。

    文件中的访问模式:

        

    判断文件是否正确打开

FILE *fp;
fp=fopen("文件目录""文件中的访问模式");
if(fp==NULL)
{
    printf("\n不能打开该文件!");
    getch();
    exit(1);
}

    关闭文件使用fclose()

        int fclose(FILE *fp);

    返回值为0则表示关闭成功,若返回非0值则表示有错误发生。

    由系统打开的标准设备文件,系统会自行关闭。

    获取文件的属性:

        获取文件描述字:int fileno(FILE *fp);

        根据文件描述字获取对应文件大小:long filelength(int handle_no);

 

三、文件的顺序读写

    顺序读写是指将文件从头到尾逐个数据读出或写入。

    单字符读写函数:fgetc()和fputc():

int fgetc(FILE *fp);

            功能为:读取文件指针fp目前所指文件位置中的字符,读取完毕,文件指针自动往下移一个字符位置,若文件指针已经到文件结尾,返回-1。

            返回值:成功则返回读取到的字符,失败返回-1.

            fgetc()函数调用中,读取的文件必须是以读或读写的方式打开的。

int fputc(char ch,FILE *fp);

            功能为:把字符ch写入文件指针fp所指向文件的位置。

            返回值:成功时返回字符的ASCII码,失败时返回EOF(在stdio.h中,符号常量EOF的值等于-1)。

            被写入的字符可以用写、读写、追加方式打开。

    字符串读写函数:fgets()和fputs():

char *fgets(char *str,int n,FILE *fp);

            功能为:在文件指针fp所指文件位置读取n个字符并放入str字符数组。

            返回值:如果读不到字符串时返回NULL。

int fputs(char *str,FILE *fp);

            功能为:将字符串str写入文件指针fp所指文件的位置。

            返回值:写入数据成功时返回非0值,写入失败时返回EOF。

    格式化字符串读写函数:fscanf()和fprintf():

int fscanf(FILE *fp,"格式化字符串",【输入项地址表】);

            功能为:从文件指针fp所指向的文件中按照格式字符串指定的格式将文件中的数据送到输入项地址表中。

            返回值:读取数据成功返回所读取数据的个数,并将数据按照指定格式存入内存中的变量或数组中,文件指针自动向下移动。读取失败返回EOF。

int fprintf(FILE *fp,"格式化字符串",【输入项地址表】);

            功能为:将输出项表中的变量值按照格式字符串制定的格式输出到文件指针fp所指向的文件位置。

            返回值:成功返回输出字符数,失败则返回负值。

    数据块读写函数:fread()和fwrite:

int fread(void *buffer,int size,int count,FILE *fp);

            功能为:从文件指针fp所指向的文件的当前位置开始,一次读入size个字节,重复count次,并将读取到的数据存到buffer开始的内存区中,同时将读写位置指针后移size*count次。

            返回值:该函数的返回值是实际读取的count值。

int fwrite(void *buffer,int size,int count,FILE *fp);

            功能为:从buffer所指向的内存区开始,一次输出size个字节,重复count次,并将输出的数据放入fp所指向的文件中,同时将读写位置指针后移size*count次。

            返回值:返回实际写入的数据项个数count。

 

四、文件的随机读写

    随机读写可移动文件内部的位置指针到需要读写的位置,再进行读写,这种读写称为随机读写。实现文件的随机读写关键是要按要求移动位置指针,这成为文件的定位。

void rewind(FILE *fp);

            功能为:将文件内部的位置指针移到文件的开始位置。

int fseek(FILE *fp,long offset,int whence);

            功能为:文件指针由whence地址移到offset的地址。

            返回值:

                对应文件的指针偏移,在函数定义中并没有真正的说明清楚返回值,对于offset当为正数的时候是向文件尾偏移的,当为负数的时候是向文件头方向偏移的,这里主要是要注意偏移的大小和文件大小边界的关系。

                当offset是向文件尾方向偏移的时候,无论偏移量是否超出文件尾,fseek都是返回0,当偏移量没有超出文件尾的时候,文件指针式指向正常的偏移地址的,当偏移量超出文件尾的时候,文件指针是指向文件尾的。并不会返回偏移出错-1值。

                当offset是向文件头方向偏移的时候,如果offset没有超出文件头,是正常偏移,文件指针指向正确的偏移地址,fseek返回值为0.当offset超出文件头时,fseek返回出错-1值,文件指针不变还是处于原来的地址。

long ftell(FILE *_File);

            功能为:得到流式文件的当前位置,用相对于文件开头的位移量来表示。由于文件中的位置指针经常移动,人们往往不容易知道其当前位置。用fell函数即可以得到当前位置。

            返回值:如果返回-1L,表示出错。

int putw(int _Ch,FILE *_File);

            功能为:将整数_Ch输出到fp指向的文件。

int __cdecl getw(FILE *_File);

            功能为:从磁盘文件都一个整数到内存最为返回值。

 

五、出错检查

    C语言中常用文件检测函数来检查输入/输出函数调用中的错误。

int feof(FILE *fp);

            功能为:判断指针fp是否处于文件结束的位置。

            返回值:如文件结束,返回值为1,否则为0。 

int ferror(FILE *fp);

            功能为:检查文件在用各种输入/输出函数进行读写时是否出错。

            返回值:如果ferror返回值为0表示未出错,否则表示出错。

            注意:对同一个文件每一次调用输入/输出函数,均产生一个新的ferror函数值,因此,应当在执行fopen函数时,ferror函数初始值自动置0。

int clearerr(FILE *fp);

            功能为:本函数用于清除出错标志和文件结束标志,使它们为0值。假设在调用一个输入/输出函数时出现错误,ferror函数值为一个非0值。在调用clearerr(fp)后,ferror(fp)的值变为0。

            只要出现错误标志,就会一直保留,知道对同一文件调用clearerr函数或rewind函数,或任何其他一个输入/输出函数。

 

六、低级I/O函数与标准I/O函数

    系统输入/输出函数,或称低级I/O函数,在内存访问数据并不提供缓冲区,因此只要一有数据需要做访问操作时,便直接向磁盘作Disk I/O。此类文件函数的优点是不必占用内存空间作为缓冲区,直接向磁盘的数据文件进行读写的操作,如果不幸死机,只会影响目前正在读写的数据。其缺点就是数据访问时会造成磁盘I/O次数太过频繁而影响程序运行的速度,而且此类函数是以文件描述字来代替文件指针,且不提供格式化的处理功能。

    由于现行的C版本,基本使用的都是缓冲文件系统,即标准输入/输出函数,所以,关于非缓冲文件系统的系统输入/输出函数在这里就不再详细介绍。

 

posted @ 2016-06-19 15:10  凝果屋的韩亦乐  阅读(7230)  评论(0编辑  收藏  举报