分类 | 函数名 | 功能 |
---|---|---|
打开文件 | fopen() | 打开文件 |
关闭文件 | fclose() | 关闭文件 |
========= | =============== | ================================= |
fseek() | 改变文件位置指针的位置 | |
文件定位 | rewind() | 使文件位置指针重置于文件开头 |
ftell() | 返回文件位置指针的当前值 | |
========= | =============== | ================================= |
fgetc(),getc() | 从指定文件取得一个字符 | |
fputc(),putc() | 把字符输出到指定文件 | |
fgets() | 从指定文件读取字符串 | |
fputs() | 把字符串输出到指定文件 | |
文件读写 | getw() | 从指定文件读取一个字(int型) |
putw() | 把一个字(int型)输出到指定文件 | |
fread() | 从指定文件中读取数据项 | |
fwrite() | 把数据项写到指定文件 | |
fscanf() | 从指定文件按格式输入数据 | |
fprintf() | 按指定格式将数据写到指定文件中 | |
========= | =============== | ================================= |
文件状态 | fputs() | 把字符串输出到指定文件 |
getw() | 从指定文件读取一个字(int型) |
1.打开文件
打开文件就是建立文件的各种有关信息,并使文件指针指向该文件,来实现其他操作。打开文件使用fopen()函数。
fopen()函数:
原型:FILE *fopen(char *filename,char *mode);
功能:使用mode模式打开指定的filename文件,若打开成功返回一个FILE类型的指针;失败则返回NULL。
参数:filename用来设定打开的文件。mode用来设定要打开的文件类型和指定文件的访问模式,并且必须为字符串格式。
示例:打开E盘下code文件夹下的文本文件test.txt。
① 程序中给出指定的文件名及其路径(嵌入式文件方法)
FILE *fp;
fp=fopen("e:/code/test.txt","rt");
② 键盘键入所要打开的文件名及其路径(交互式文件方法)
FILE *fp;
char filename[40];
gets(filename);
fp=fopen(filename,"r");
2.关闭文件
文件打开以后若不再使用就要用fclose()函数将指定文件关闭,并将FILE文件指针的相关资源及所占用的缓冲区归还给系统。
fclose()函数:
原型:int fclose(FILE *fp);
功能:将文件指针fp所指的文件关闭。若返回0,表示关闭成功;若返回非0,则表示有错误发生。
示例:fclose(fp);
注意:写入模式(“w”)一定要用fclose()函数关闭文件,否则放在缓冲区的数据无法写回文件,从而发生数据遗失的情况。因为当文件写入数据时,是先将数据写到缓冲区,等到缓冲区充满后再整块传送到磁盘文件中。如果程序结束时,缓冲区还没有充满,则其中的数据并没有传到磁盘上,所以必须使用fclose()函数关闭文件,强制系统将缓冲区中的所有数据送到磁盘,并释放该文件指针变量。
3.获取文件的属性
如果想知道某一个文件的大小,可以使用fileno()和filelengh()函数实现。
fileno()函数:
原型:int fileno(FILE *fp);
功能:返回所打开文件指针fp对应的文件描述字(handle_no)。当打开文件成功后,操作系统会自动赋予一个号码,此号码用来代表所打开的文件。所在头文件stdlib.h。
filelength()函数:
原型:long filelength(int handle_no);
功能:返回文件描述子对应的文件大小,单位为字节。所在头文件io.h。
示例:想知道E盘下code文件里test.txt文件大小,程序如下:
FILE *fp;
int fno,fsize;
fp=fopen("e:/code/test.txt","re");
fno=fileno(fp);
fsize=filelength(fno);
fclose(fp);
4.文件的顺序书写
根据文件的读写方式不同,文件可分为文件的顺序读写和随机读写。顺序读写是指将文件从头到尾逐个数据读出或写入,也是通过函数实现。
单字符读写函数:fgetc和fputc
字符串读写函数:fgets和fputs
格式化字符串读写函数:fscanf和fprintf
数据块读写函数:fread和fwrite
① 单字符读写函数
fgetc()函数:读单字符函数
原型:int fgetc(FILE *fp);
功能:读取文件指针fp目前所指文件位置中的字符,读取完毕,文件指针自动往下移一个字符位置,若文件指针已经到文件结尾,返回-1。
示例:ch=fgetc(fp); //从fp所指的文件中读取一个字符并送入ch。
注意:调用该函数时,读取的文件必须是以读或读写的方式打开。
fputc函数():写单字符函数
原型:int fputc(char ch,FILE *fp)
功能:把字符ch写入文件指针fp所指向文件的位置,成功时返回字符的ASCII码,失败时返回EOF。
示例:把字符a写入fp所指向的文件中。
FILE *fp;
fputc('a',fp);
【例1:从键盘上输入字符串追加添写到指定的文件中】
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <io.h>
#define LEN 100
int main()
{
FILE *fp;
char filename[LEN],data[LEN];
int fno,fsize,i;
char ch,judge;
printf("写文件程序...\n\n");
printf("请输入要打开文件的完整路径及文件名:");
gets(filename);
fp=fopen(filename,"a+"); //文件以追加方式写
if(fp==NULL)
{
printf("\n打开文件失败,%s可能不存在\n",filename);
exit (1);
}
fno=fileno(fp); //获取文件描述字
fsize=filelength(fno); //计算文件大小
printf("\n%s文件打开!\n",filename);
printf("\n文件大小为:%d Bytes\n",fsize);
printf("\n文件内容为:");
while((ch=fgetc(fp))!=EOF)
printf("%c",ch);
while(1)
{
printf("\n\n请问是否要添加数据(Y/N):");
scanf("%c",&judge);
getchar();
if(judge=='Y')
{
printf("\n\n请输入要添加的数据:");
gets(data);
for(i=0;i<strlen(data);i++)
fputc(data[i],fp);
printf("\n");
}
else
{
fclose(fp);
break;
}
}
fp=fopen(filename,"rt");
if(fp==NULL)
{
printf("\n打开文件失败,%s可能不存在\n",filename);
exit(1);
}
fno=fileno(fp);
fsize=filelength(fno);
printf("\n\n%s文件打开!\n",filename);
printf("\n文件大小%d Bytes\n",fsize);
printf("\n文件内容:");
while((ch=fgetc(fp))!=EOF)
printf("%c",ch);
fclose(fp);
printf("\n\n");
return 0;
}
运行结果如下:
② 字符串读写函数
fgets()函数:读字符串函数
原型:char *fgets(char *str,int n,FILE *fp);
功能:在文件指针fp所指文件位置读取n个字符并放入str字符数组。如果读不到字符串时返回NULL。
示例:
FILE *fp;
char str[10];
fp=fopen("e:\\code\\test.txt","rt");
while((fgets(str,10,fp)!=NULL)
printf("%s",str);
fputs()函数:写字符串函数
原型:int fputs(char *str,FILE *fp);
功能:将字符串str写入文件指针fp所指文件的位置。写入数据成功时返回非0值,写入失败时返回EOF。
示例:
FILE *fp;
char str[10];
fp=fopen("e:\\code\\test.txt","rt");
gets(str);
fputs(str,fp);
【例2:利用fgets()函数和fputs()函数实现例1】
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <io.h>
#define LEN 100
int main()
{
FILE *fp;
char filename[LEN],data[LEN],temp[LEN];
int fno,fsize;
char judge;
printf("写文件程序...\n\n");
printf("请输入要打开文件的完整路径及文件名:");
gets(filename);
fp=fopen(filename,"a+"); //文件以追加方式写
if(fp==NULL)
{
printf("\n打开文件失败,%s可能不存在\n",filename);
exit (1);
}
fno=fileno(fp); //获取文件描述字
fsize=filelength(fno); //计算文件大小
printf("\n%s文件打开!\n",filename);
printf("\n文件大小为:%d Bytes\n",fsize);
printf("\n文件内容为:");
while((fgets(temp,LEN,fp))!=NULL)
printf("%s",temp);
while(1)
{
printf("\n\n请问是否要添加数据(Y/N):");
scanf("%c",&judge);
getchar();
if(judge=='Y')
{
printf("\n\n请输入要添加的数据:");
gets(data);
fputs(data,fp);
}
else
{
fclose(fp);
break;
}
}
fp=fopen(filename,"r");
if(fp==NULL)
{
printf("\n打开文件失败,%s可能不存在\n",filename);
exit(1);
}
fno=fileno(fp);
fsize=filelength(fno);
printf("\n\n%s文件打开!\n",filename);
printf("\n文件大小%d Bytes\n",fsize);
printf("\n文件内容:");
while((fgets(temp,LEN,fp))!=NULL)
printf("%s",temp);
fclose(fp);
printf("\n\n");
return 0;
}
③ 格式化字符串读写函数
fscanf()函数:格式化字符串读函数
原型:int fsanf(FILE *fp,"格式化字符串",【输入项地址表】);
功能:从文件指针fp所指向的文件中按照格式字符串指定的格式将文件中的数据送到输入项地址表中。若读取数据成功会返回所读取数据的个数,并将数据按照指定格式存入内存中的变量或数组中,文件指针自动向下移动;若读取失败则返回EOF。
示例:从该文件中读取出该条数据给指定的变量。首先,以读方式打开指定文件,然后将文件中的学号“04161076”、姓名“鸭鸭”、性别“女”分别赋给字符数组num、name和sex。
char num[20],name[40],sex[5];
FILE *fp;
fp=fopen("e:\\code\\test.txt","rt");
fscanf(fp,"%s %s %s",num,name,sex);
fprintf()函数:格式化字符串写函数
原型:int fprintf(FILE *fp,"格式化字符串",【输入项地址表】);
功能:将输出项表中的变量值按照格式字符串指定的格式输出到文件指针fp所指向的文件位置。
示例:首先初始化要追加的数据,然后以追加写方式打开指定文件。
char num[20]=“04161075”,name[40]=“喵喵”,sex[5]=“女”;
FILE *fp;
fp=fopen("e:\\code\\test.txt","a+");
fputc('\n',fp); //写入一个回车换行
fscanf(fp,"%s %s %s",num,name,sex);
【例3:输入3个学生的数据并保存到磁盘文件中,再读出数据并显示在屏幕上】
#include <stdio.h>
#include <stdlib.h>
#define N 3
struct stu
{
char num[20];
char name[30];
char sex[5];
}class[N];
int main()
{
FILE *fp;
int i;
printf("\n输入该班的数据:\n");
fp=fopen("class_list.txt","wt");
if(fp==NULL)
{
printf("不能打开此文件,按任意键退出!");
exit(1);
}
for(i=0;i<N;i++)
{
printf("\n第%d个人的信息:\n",i+1);
printf("\n学号:");
gets(class[i].num);
printf("\n姓名:");
gets(class[i].name);
printf("\n性别:");
gets(class[i].sex);
fprintf(fp,"%s %s %s\n",class[i].num,class[i].name,class[i].sex);
}
fclose(fp);
fp=fopen("class_list.txt","rt");
printf("该班数据为:\n");
printf("学号 姓名 性别\n");
i=0;
while(fscanf(fp,"%s %s %s",class[i].num,class[i].name,class[i].sex)!=EOF)
{
printf("%s %s %s\n",class[i].num,class[i].name,class[i].sex);
i++;
}
fclose(fp);
return 0;
}
运行结果如下:
注意:fscanf()函数在读取数据时以空格作为数据与数据之间的间隔,所以姓名之间带空格输入时,虽然写入正确,但是读取数据时就会发生错误。要解决这个问题就要使用fread()和fwrite()函数。
④ 数据块读写操作
fread()函数:数据块读函数
原型:int fread(void *buffer,int size,int count,FILE *fp);
功能:从文件指针fp所指向的文件的当前位置开始,一次读入size个字节,重复count次,并将读取到的数据存到buffer开始的内存区中,同时将读写位置指针后移size*count次。该函数的返回值是实际读取的count值。
buffer:是一个指针,在fread函数中,它表示存放读入数据的首地址。在fwrite函数中,它表示要输出的数据在内存中的首地址。
size:表示数据块的字节数。
count:表示要读写的数据块块数。
示例:从fp所指的文件中,每次读4个字节(一个实数)送入实型数组fa中,连续读5次,即读5个实数到fa中。
float fa[5];
fread(fa,4,5,fp);
fwrite()函数:数据块写函数
原型:int fwrite(void *buffer,int size,int count,FILE *fp);
功能:从buffer所指向的内存区开始,一次输出size个字节,重复count次,并将输出到的数据存入fp所指向的文件中,同时将读写位置指针后移size*count次。
示例:从fa实型数组中,每次读4个字节(一个实数)写入fp所指的文件中,连续读写5次,即读5个实数写到fp所指的文件中。
一个结构体类型数据如下:
struct student_type
{
char name[20];
int num;
int age;
char addr[30];
}stu[40];
写入文件:(每次写一个)
for(i=0;i<40;i++) //前提是stu数组中40个元素都已经有值存在
fwrite(&stu[i],sizeof(struct student_type),1,fp);
或只写一次:
fwrite(stu,sizeof(struct student_type),40,fp);
从磁盘文件读出:(每次读一个)
for(i=0;i<40;i++) //前提是fp所指向的文件中也有值存在
fread(&stu[i],sizeof(struct student_type),1,fp);
或只读一次:
fread(stu,sizeof(struct student_type),40,fp);
【例4:利用fread()和fwrite()函数实现例3】
#include <stdio.h>
#include <stdlib.h>
#define N 3
struct stu
{
char num[20];
char name[30];
char sex[5];
}class[N];
int main()
{
FILE *fp;
int i;
printf("\n输入该班的数据:\n");
fp=fopen("class_list.txt","wt");
if(fp==NULL)
{
printf("不能打开此文件,按任意键退出!");
exit(1);
}
for(i=0;i<N;i++)
{
printf("\n第%d个人的信息:\n",i+1);
printf("\n学号:");
gets(class[i].num);
printf("\n姓名:");
gets(class[i].name);
printf("\n性别:");
gets(class[i].sex);
fwrite(&class[i],sizeof(struct stu),1,fp);
}
fclose(fp);
fp=fopen("class_list.txt","rt");
printf("\n该班数据为:\n");
printf("学号 姓名 性别\n");
i=0;
while(fread(&class[i],sizeof(struct stu),1,fp)!=NULL)
{
printf("%s %s %s\n",class[i].num,class[i].name,class[i].sex);
i++;
}
fclose(fp);
return 0;
}
注意:这两个函数可以通过文件的大小和每个结构的大小计算出文件中实际含有的记录个数。
fno=fileno(fp);
fsize=filelength(fno);
fnum=fsize/sizeof(struct stu); //fnum为文件中记录个数
5.文件的随机读写
如果想只读写文件中某一指定的部分,可移动文件内部的位置指针到需要读写的位置,再进行读写。这种读写称为随机读写。实现的关键是要按要求移动位置指针,称为文件的定位。
rewind()函数:
原型:void rewind(FILE *fp);
功能:将文件内部的位置指针移到文件的开始位置。
【例5:实现在已经存在的指定文件末尾追加一个可带空格的字符串】
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
FILE *fp;
char ch,str[20];
fp=fopen("string.txt","at+");
if(fp==NULL)
{
printf("不能打开此文件,按任意键退出!");
exit(1);
}
printf("请输入一个字符串:\n");
gets(str);
fwrite(str,strlen(str),1,fp); //将数组str中的字符串写入文件中
rewind(fp); //将文件指针fp重新移回文件首部
ch=fgetc(fp);
while(ch!=EOF)
{
putchar(ch);
ch=fgetc(fp);
}
printf("\n");
fclose(fp);
return 0;
}
fseek()函数:
原型:int fseek(FILE *fp,long offset,int whence);
功能:文件指针由whence地址移到offset的地址。
示例:读取文件中第n个记录的数据的程序如下。把文件指针由0地址往后移sizeof(struct stu)*n地址,即表示文件指针后移n个数据记录的地址,读出当前文件指针所指的数据给student。
rewind(fp);
fseek(fp,sizeof(struct stu)*n),0);
fread(&student,sizeof(struct stu),1,fp);
【例6:在例4的class_list.txt学生文件中读出第二个学生的数据】
#include <stdio.h>
#include <stdlib.h>
struct stu
{
char num[20];
char name[30];
char sex[5];
}q;
int main()
{
FILE *fp;
int i=1;
printf("\n输入该班的数据:\n");
fp=fopen("class_list.txt","rt");
if(fp==NULL)
{
printf("不能打开此文件,按任意键退出!");
exit(1);
}
fseek(fp,sizeof(struct stu)*i,0);
fread(&q,sizeof(struct stu),1,fp);
printf("\n该班第二个学生的数据信息为:\n");
printf("\n学号 姓名 性别\n");
printf("%s %s %s\n",q.num,q.name,q.sex);
return 0;
}
ftell()函数:
原型:int ftell(FILE *fp);
功能:得到流式文件的当前位置(相对于文件开头的位移量)。若返回值为-1L表示出错。
示例:
i=ftell(fp);
if(i==-1L)
printf("Error\n");
其他读写函数:
putw()函数:
原型:int putw(int i,FILE *fp);
功能:将整数i输出到fp指向的文件。
示例:
putw(int i,FILE *fp) //若调用putw(10,fp)
{
char *s;
s=&i; //将i的地址赋给指针变量s
putc(s[0],fp); //s指向i的第1个字节==*(s+0),输出字节内容
putc(s[1],fp); //s指向i的第2个字节==*(s+1),输出字节内容
return(1);
}
getw()函数:
原型:int getw(FILE *fp);
功能:从磁盘文件读一个整数到内存
示例:
getw(FILE *fp)
{
char *s;
int i;
s=&i; //将i的地址赋给指针变量s
s[0]=getc(fp);
s[1]=getc(fp);
return(1);
}
6.出错检查
C语言常用文件检测函数检查输入/输出函数调用中的错误。
feof()函数:
原型:int feof(FILE *fp);
功能:判断文件指针fp是否处于文件结束的位置。若文件结束,则返回1,否则为0。
ferror函数():
原型:int ferror(FILE *fp)
功能:检查文件在用各种输入/输出函数进行读写时是否出错。若返回0表示正确,否则出错。
注意:该函数的初始值自动置0。
clearerr函数():
原型:int clearerr(FILE *fp)
功能:清除出错标志和文件结束标志,使他们置为0.
注意:该函数的初始值自动置0。