14、文件
文件是一组相关数据的有序集合,是程序设计中的一个重要概念。通常情况下,使用计算机主要是在使用文件。要进行数据处理,往往也需要通过文件来完成。
14.1、文件概述
文件是一组相关数据的有序集合,这个数据集有一个名称,叫做文件名。
通常情况下,使用计算机主要是在使用文件。输入和输出指的是从标准输入设备(键盘)输入,由标准输出设备(显示器或打印机)输出。磁盘作为信息载体,用于保存中间结果或最终数据。在使用一些字处理时,打开文件可以将磁盘的信息输入内存,关闭文件可将内存的数据输出到磁盘。这时,输入、输出都是针对文件系统的。
所有文件都可以通过流进行输入、输出操作。与文件流和二进制流相对应,文件可以分为文本文件和二进制文件两大类。文本文件也成为称为ASCII文件,保存时每个字符对应一个字节,存放对应的ASCII码。二进制文件按二进制编码方式保存文件内存。
按文件内容看,可分为源文件、目标文件、可执行文件、头文件和数据文件等。
从用户角度(或所依附的介质)看,可分为普通文件和设备文件两种。
普通文件:指存储在磁盘或其他外部介质上的有序集合。
设备文件:指与主机相连的各种外部设备,如显示器、打印机、键盘等。操作系统中把外部设备也看作一个文件来管理,把他们的输入、输出等同于对磁盘文件的读和写。
C语言中,文件操作都是由库函数来完成的。
14.2、文件基本操作
文件的基本操作包括文件的打开和关闭。除标准的输入、输出文件外,其他所有文件都必须先打开在使用,使用后必须关闭该文件。
14.2.1、文件指针
文件指针是一个指向文件有关的指针,这些信息包括文件名,状态和当前位置,保存在一个结构体变量中。使用文件时需要在内存中为其分配空间,用来存放文件的基本信息。该结构体类型是由系统定义的,C语言规定该类型为FILE型,其声明如下:
上述代码中,使用了typedef定义了一个结构体类型FILE,编写程序时可以直接使用FILE类型来定义变量。注意,定义变量时不必将结构体内容全部给出,只需写成如下形式:
FILE *fp;
注:不可以通过定义FILE类型变量来操作文件。FILE型数据对象的位置由库函数确定,C语言中只能通过FILE *类型的指针来操作文件。
14.2.2、打开文件(fopen函数)
fopen函数用来打开一个文件,打开文件的操作就是创建一个流。fopen函数的原型在stdio.h中,其一般形式如下:
FILE *fp;
fp=fopen(文件名,使用文件方式);
其中,“使用文件方式”指打开文件时的读写方式(如表所示)
例如:以只读方式打开名为123的文本文档,代码如下:
FILE *fp;
fp=fopen("123.txt","r");
如果fopen函数打开文件成功,返回一个有确定指向的FILE类型指针;若打开失败,则返回NULL。文件打开失败通常情况下是以下三个原因。
1、 指定的盘符或路径不存在。
2、 文件名中含有无效字符。
3、以“r”模式打开一个不存在的文件。
14.2.3、关闭文件(fclose)
文件使用完毕以后,应使用fclose函数将其关闭。fclose函数的原型也在stdio.h中,其一般形式如下:
fclose(文件指针);
正常关闭文件时,fclose函数返回0,否则返回EOF。例如:
fclose(fp);
注:在程序结束之前应关闭所有文件,以防止因未关闭文件而造成数据丢失。
14.3、文件的读写
打开文件后,可进行数据读取或写入的操作。C语言提供了丰富的文件读写操作函数。
14.3.1、写入字符(fputc函数)
fputc函数用于把一个字符写到磁盘文件(fp所指向的文件)中。一般形式如:
fputc(ch.fp);
其中,ch是要写入的字符,可以是一个字符常量,也可以是一个字符变量。fp是文件指针变量,如果函数写入成功,则返回值就是写入的字符:如果写入失败,则返回EOF。
注:上述代码中用到了C语言中的stlib.h标准库头文件,他包含了C语言中常用的系统函数,这里主要使用其提供的exit函数,用来在指定条件下退出程序。
14.3.2、读取字符(fgetc函数)
fgetc函数用于从指定文件(fp指向的文件)中读取一个字符。一般形式如下:
fgetc(fp);
注意,文件必须以只读或读写方式打开。当函数遇到文件结束符时,将返回文件结束标识EOF。
注:fgets函数和gets函数的区别是:gets函数读完回车换行(‘\n’),并不存储;fgets函数存储换行符并在其后写一个null cahracter(‘\0’)。不能简单地把fgets函数理解为gets函数限制字符数目的stdion加强版。在改用fgets函数后,应把字符串结束前的‘\n’删除。
14.3.3、写入字符串(fputs函数)
fputs函数与fputs函数类似,用于指向文件写入一个字符串。一般形式如下:
fputs(字符串,文件指针)
其中,字符串可以是字符串常量,也可以是字符数字名、指针或变量。例:
14.3.4、读取字符串(fgets函数)
fgets函数与fgetc函数类似,用于指定文件中读取一个字符串到字符数组中。一般形式如下:
fgets(字符数组名,n,文件指针);
其中n表示读取字符串字符的个数(包含“\n”)。
例:创建一个文件,文件内容显示到控制台上
14.3.5、fprintf函数
printf和scanf函数,两者都是格式化读写函数。fpintf和fscanf函数与之相似,但读写对象不是终端,而是磁盘文件。
fprintf函数的功能为:根据指定的格式,将数据输出到文件中。对系统而言,这是一个输出的过程,对文件而言,这是一个写入的过程,一般形式如下:
fprinyf(文件类型指针,格式字符串,输出列表);
例如,以下代码将整形变量i的值以“%d”的格式输出到fp指向的文件中。
fprintf(fp,“d%”,i);
14.3.6、fscanf函数
fscanf函数的功能为:从文件中读取数据,遇到空格和换行符时结束。对系统而言,这是一个输入数据的过程;对文件而言,这是一个读取数据的过程。一般形式如下:
fscanf(文件类型指针,格式字符串,输入列表);
例如,下面语句的作用是读取fp指向文件中i的值。
fscanf(fp,“%d”,&i);
14.3.7、读写数据块(fread和fwrite函数)
实际开发中,往往需要对整块数据进行读写,例如,对一个结构体变量进行读写。下面介绍可实现整块读写功能的fread和fwrite函数。
fread函数的功能是:从fp指向的文件中读取count次,每次读size字节,读取的信息保存在buffer地址中。一般形式如下:
fread(buffer,size,count,fp);
fwrite函数的功能是:将buffer地址开始的信息输出count次,每次写size字节到fp指向的文件中,一般形式如下:
fwrite(buffer,size,count,fp);
1、buffer:一个指针。对fwrite函数来说,是待输出数据的地址(起始地址),对fread函数来说,是待读取数据存放的地址。
2、size:要读写的字节数。
3、count:要读写多少个size字节的数据项。
4、fp:文件指针
例如:下面的语句表示从fp指向的文件中每次读取两个字节并保存在数组a中,连续读取三次。
fread(a,2,3,fp);
下面的语句表示将数组a中的信息每次输出两个字节到fp指向的文件中,连续输出3次。
fwrite(a,2,3,fp);
14.4、文件的定位
对文件进行操作,往往不需要从文件首开始,只操作指定内容即可,这时,就需要使用文件定位函数来实现数据的随机读取。
14.4.1、fseek函数
fseek函数的作用是移动文件内部的位置指针。一般形式如下:
fseek(文件类型指针,位移量,起始位置);
其中“文件类型指针”指向被移动的文件,“位移量”表示移动的字节数,一般为long型数据,以保证文件长度大于64KB时不会出错;“起始点”表示从何处开始计算位移量,一般是文件首、文件当前位置和文件尾,其表示方法如下:
例:下面的语句表示将位置指针从当前位置向后移动20个字节。
fseek(fp,-20L,1);
14.4.2、rewind函数
rewind函数用于将位置指针重返文件首,没有返回值。一般形式如下:
int rewind(文件类型指针)
14.4.3、fell函数
ftell函数可得到流式文件的当前位置,并使用相对于文件首的位移量表示。一般形式如下:
long ftell(文件类型指针)
当ftell函数的返回值为-1L时,表示出错。
14.5、文件管理
14.5.1、删除文件(remove函数)
remove函数的作用是删除文件,其一般形式如下:
remove(char *name);
删除name指定的文件,删除成功则返回0。出现错误则返回-1.remove函数的原型在stdio.h中。
14.5.2、重命名文件(rename)
rename函数的作用是重命名文件。一般形式如下:
int rename(char *oldfname,char *newfname)
oldname和newfname中的目录可以不同,因此可用remove把文件从一个目录移到另一个目录。该函数的原型在stdio.h中,函数调用成功时候返回0,出错时返回非零值。
使用rename函数不光可以重命名文件,还可以重命名目录,下面介绍两者使用时候的注意事项:
1、如果newname指定的文件存在,则会被删除。
2、如果newname与oldname不在同一个目录下,则相当于移动文件。
重命名目录注意:
1、如果oldname和oldname都为目录,则重命名目录。
2、如果newname指定的目录存在且为空目录,则先将newname删除。
3、对应newname和oldname两个目录,调用进程必须有写权限。
4、重命名目录时,newname不能用oldname作为路径前缀。例如不能将/usr更换为/usr/foo/testdir,因为/usr是新名字的路径前缀,因而不能将其删除。
14.5.3、复制文件
复制文件的需要注意的是,复制过程中无论是复制的文件还是被复制的文件都应该处于打开的状态,复制完成后在将两个文件分别关闭。
14.6、文件状态检测
14.6.1、文件读取结束检测(feor函数)
文件读取过程中,当函数遇到文件结束符时,将返回文件结束标注EOF。但是光凭EOF,很难判断程序是调用失败还是文件读取结束。
feor函数用于判断是否读取到文件尾,一般形式如下:
feor(文件指针);
判断文件是否处于文件结束位置,如果文件结束,则返回值为1,否则为0。
14.6.2、文件读写出错检测(ferror函数);
ferror函数用来检测文件读写时可能出现的错误。一般形式如下:
ferror(文件指针);
如果ferror返回值为0,表示读写未出错,否则表示读写出错。
14.6.3、清除状态标志(clearerr函数)
clearerr()函数用来清除文件的错误标志。如果不清楚文件错误,以后读写文件时,即使没有发生错误,ferror()仍将返回非零值(认为还有错)。一般形式如下:
clearerr(文件指针);
该函数的作用是使文件错误标志和文件结束符为0。
标签:fp,文件,读取,函数,读写,C语言,第六版,第十四章,指针 From: https://blog.csdn.net/qq_63485530/article/details/143641624