文件加工厂
在“进进出出的IO”中我们学到了标准流的I/O函数,现在我们来学习一下关于对文件操作的函数
首先来看一下我们要学习哪些函数
文件函数汇总
功能 | 函数 |
---|---|
打开与关闭 | fopen(),fclose() |
读写字符 | fgetc(),fputc() |
读写字符串 | fgets(),fputs() |
按数据块读写 | fread(),fwrite() |
格式化读写 | fscanf(),fprintf() |
文件定位 | fseek(),rewind(),ftell() |
判断文件是否结束 | feof() |
fopen()
- 函数原型:FILE *fopen(char const *name,char const *mode)
- 函数说明
- fopen()函数用于打开一个特定的文件,第一个参数name是要打开文件的名字,注意路径;第二个参数是打开文件的方式,用于指定文件流的作用;下面将列出打开方式。
文件打开方式 | 含义 |
---|---|
“r” | 以只读方式打开文本文件 |
“w” | 以只写方式建立并打开文本文件,若存在同名文件,则被覆盖 |
“a” | 以只写方式打开文本文件,位置指针指向文件尾,向文件尾增加数据,原数据保留 |
“r+” | 以读写方式打开文本文件 |
“w+” | 为读写建立一个新的文本文件 |
“a+” | 以读写方式打开文本文件 |
“rb” | 以只读方式打开二进制文件 |
“wb” | 以只写方式打开二进制文件 |
“ab” | 以只写方式打开二进制文件,位置指针指向文件尾,向文件尾增加数据,原数据保留 |
“rb+” | 以读写方式打开二进制文件 |
“wb+” | 为读写建立一个新的二进制文件 |
“ab+” | 以读写方式打开二进制文件 |
- 如果成功:fopen()的返回值是一个文件类型(FILE)的指针。如果失败:返回值是NULL
fclose()
- 函数原型:int fclose(FILE*fp)
- 函数说明
- 为文件关闭函数,fclose()函数在文件关闭之前会刷新缓冲区,从而保证数据的完整性
- fclose()有一个int类型的返回值,当关闭文件成功时返回值为0,否则返回EOF(常量:值为-1)。
fgetc()
- 函数原型:int fgetc(FILE*fp)
- 函数说明
- 从指定文件读取一个字符,该文件必须以只读或者只写方式打开。
- 函数有一个参数,为指向要操作文件的指针。fgetc()从fp中读出一个字符并返回这个字符的ASCII码,若读到文件结束符则函数返回文件结束标志EOF
fputc()
- 函数原型:int fputc(int c,FILE*fp)
- 函数说明
- 把一个字符写到文件中。函数有两个参数,第一个参数c为要写入的字符,可以是一个字符常量也可以是一个字符变量;
- 第二个参数为指向要操作的文件的指针。fputc()将字符写入fp指向的文件中。
- 若写入成功则返回字符c的ASCII码;若失败返回EOF
#include <stdio.h>
#include <stdlib.h>
/*
主要目的:一次读取或者写入一个字符
将first中的内容复制到second中
记得在当前文件目录下创建两个文本文件
first.txt && second.txt
并且往两个文件中自定义一些内容,便于查看
*/
int main(void)
{
FILE *fp1,*fp2;
if((fp1=fopen("first.txt","r"))==NULL)//以只读方式打开文本文件
{
printf("打开文件first错误!\n");
exit(1);
}
if((fp2=fopen("second.txt","a"))==NULL)//以只写方式打开文本文件
{
printf("打开文件second错误!\n");
exit(1);
}
char ch;
while((ch=fgetc(fp1))!=EOF)
{
fputc(ch,fp2);
}
//最后关闭文件,这一步很重要
fclose(fp1);
fclose(fp2);
return 0;
}
fgets()
- 函数原型:char * fgets(char * s,int n,FILE*fp)
- 函数说明
- 从指定的文件读取一个字符串。
- 第一个参数为暂存要读取字符串的缓冲区,通常定义一个数组
- 第二个参数为一次读取的字符个数
- 第三个参数fp为指向要操作的文件的指针。
- fgets()从fp指向的文件中读取字符,当读到换行回车符、文件末尾或满n-1个字符时在字符串末尾加上’\0’把它们放到字符数组s中后函数返回。
- 若在任何字符读取前就达到了文件末尾,fgets()返回NULL指针,否则返回s的首地址
fputs()
- 函数原型:int *fputs(const char *s,FILE *fp)
- 函数说明
- 向指定的文件输入一个字符串。
- 第一个参数s是要写入到文件的字符串,可以是字符串常量、字符数组或者字符型指针,字符串应以’\0’结尾;
- 第二个参数fp为指向要操作的文件的指针。fputs()将s中的字符逐字写入fp所指向的文件。若写入成功函数返回0,否则返回EOF(-1)
应用展示:
#include <stdio.h>
#include <stdlib.h>
#define BUFFER_SIZE 50//字符串缓冲区的大小
/*
主要功能:复制文件,一次读取或写入一个字符串
将first中的内容复制到second中
记得在当前文件目录下创建两个文本文件
first.txt && second.txt
并且往两个文件中自定义一些内容,便于查看
*/
int main(void)
{
FILE *fp1,*fp2;
char buffer[BUFFER_SIZE];
if((fp1=fopen("first.txt","r"))==NULL)//以只读方式打开文本文件
{
printf("打开文件first错误!\n");
exit(1);
}
if((fp2=fopen("second.txt","a"))==NULL)//以只写方式打开文本文件
{
printf("打开文件second错误!\n");
exit(1);
}
//char buffer[BUFFER_SIZE];
while(fgets(buffer,BUFFER_SIZE,fp1)!=NULL)
{
fputs(buffer,fp2);
}//end while
//最后关闭文件,这一步很重要
fclose(fp1);
fclose(fp2);
return 0;
return 0;
}
fread()
- 函数原型:unsigned fread(void *s,unsigned size,unsigned count,FILE *fp);
- 函数说明
- 从指定文件一次读入一组数据,用于读取二进制数据。如图像、音频、视频等
- 参数一是从文件中读入的数据的存放地址;
- 参数二是要读的字节数,即每个数据块的大小
- 参数三是要读多少个size字节的数据,即最多允许读的数据块的个数;
- 参数四为指向要操作的文件的指针
- 返回值是实际读到的数据块(并非字节)个数
fwrite()
- 函数原型:unsigned fwrite(const void *s,unsigned size,unsigned count,FILE *fp)
- 函数说明
- 向指定文件一次写入一组数据,用于写入二进制数据。
- 参数一是要向文件写入数据的存放地址
- 参数二是要写入的字节数。
- 参数三是要写入多少个size字节的数据块
- 参数四是fp指向要操作的文件的指针。
- 返回实际写入的数据块个数
- 应用举例
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 3
/*
主要目的:从键盘输入3个关于图书的数据,存入文件,
再从文件中取出数据显示到屏幕上
*/
//**********************描述图书信息的结构体*****************
struct book_info
{
char name[20];
char author[20];
char book_concern[30];
}bookArray[MAXSIZE];
//************************函数申明(定义)区*****************
int SaveBookInfo(const char *sName);
int DisplayBookInfo(const char *sName);
//*************主函数********************
int main(void)
{
//从键盘输入MAXSIZE个图书信息并存入结构体数组中
int i;
for(i=0;i<MAXSIZE;i++)
{
printf("请输入第%d本书相关内容\n",i+1);
printf("请输入书名:");scanf("%s",bookArray[i].name);
printf("请输入作者:");scanf("%s",bookArray[i].author);
printf("请输入出版社:");scanf("%s",bookArray[i].book_concern);
}//end for
//指定文件路径
const char *sName="bookInfo.txt";//注意这里是相对路径
//将结构体数组中的数据存放到文件中
if(SaveBookInfo(sName))
{ //从文件中读取数据并显示
DisplayBookInfo(sName);
}//end if
return 0;
}
/*
函数功能:将结构体数组中的数据存入指定文件中
函数参数:保存数据的文件路径
函数返回值:1-表示数据成功写入,0-表示出错
*/
int SaveBookInfo(const char *sName)
{
FILE *fp;
int i;
//打开要写的文件
if((fp=fopen(sName,"w"))==NULL)
{
printf("打开文件\"%s\"错误!\n",sName);//注意这里不会执行,因为以“w”方式打开文件的话,没有则会自动创建文件
return 0;
}//end if
//打开成功,向其中写入数据
for(i=0;i<MAXSIZE;i++)
{
if(fwrite(&bookArray[i],sizeof(struct book_info),1,fp)!=1)
{
printf("向文件%s中写入出错!\n",sName);
return 0;
}
}//end for
//关闭文件
fclose(fp);
return 1;
}
/*
函数功能:将指定文件中的数据取出并显示到屏幕
函数参数:保存数据的文件路径
函数返回值:1-表示数据读取成功,0-表示读取出错
*/
int DisplayBookInfo(const char *sName)
{
FILE *fp;
//打开要读的文件
if((fp=fopen(sName,"r"))==NULL)
{
printf("打开文件%s错误!\n",sName);
return 0;
}//end if
//将文件中的数据读出并显示
int i=0;
printf("name\tauthor\t\tbook_concern\n");
for(;i<MAXSIZE;i++)
{
fread(&bookArray[i],sizeof(struct book_info),1,fp);
printf("%-s\t%-s\t\t%-s\n",bookArray[i].name,bookArray[i].author,bookArray[i].book_concern);
}//end for
fclose(fp);
return 1;
}
fprintf()
- 函数原型:int fprintf(FILE *fp,const char *format,…);
- 函数说明
- fprintf()函数和printf()函数作用相似,都是格式化输出函数
- 不同的是printf()函数输出对象是终端,而fPrintf()函数输出对象是文件
- 参数一为指向要操作的文件的指针
- 后两个参数及函数的具体说明与printf()相同
fscanf()
- 函数原型:int fscanf(FILE *fp,const char *format,…)
- 函数说明
- fscanf()与scanf()类似
- 用fscanf()和fprintf()函数对文件进行格式化读写,在输入时要将ASCII码转换成二进制数,输出时又将二进制数转换成字符,时间开销比较大。
fseek()
- 函数原型:int fseek(FILE *fp,long offset,int from)
- 函数说明
- 对文件可以顺序读写也可以随机读写
- FILE中有一个指向当前读写位置的位置指针,如果顺序读写文件,每次读写一个字符,读完一个字符后,位置指针会自动移到下一个字符。
- 我们可以通过函数来改变这个指针的位置,从而实现文件的随机读写。这样的函数就是文件定位函数。
- 参数一为指向要操作的文件的指针
- 参数二offset是位移量,是以起点为基点,向前移动的字节数
- 参数三from为开始定位的起始点,其取值如下
值 | 名字 | 含义 |
---|---|---|
0 | SEEK_SET | 定位起始点为文件开始 |
1 | SEEK_CUR | 定位起始点为文件当前位置 |
2 | SEEK_END | 定位起始点为文件末尾 |
- 在使用的时候需要注意:如果from为SEEK_SET,则offset的值应该是一个非负数,因为企图定位到文件起始位置之前是不对的;若from为SEEK_END,offset的值正负都可以,当offset的值取正值时,若对文件进行写操作则会扩展这个文件,若对文件进行读操作将返回一条到达文件末尾的信息。fseek()函数一般用于二进制文件,因为文本文件要发生字符转换,计算位置时通常会发生混乱。
rewind()
- 函数原型:void rewind(FILE *fp)
- 函数说明
- 为文件定位函数,作用是使文件位置指针重新返回到文件的开头。
ftell()
- 函数原型:long ftell(FILE *fp)
- 函数说明
- 得到文件指针当前位置,用相对于文件头的位移量来表示。
feof()
- 函数原型:int feof(FILE *fp)
- 函数说明
- 用于判断文件是否结束。当文件指针指向fp尾时,函数返回非0数字,否则返回0;
总结
- 注意在程序终止之前应该关闭所有打开的文件
- fread()与fwrite()函数返回值是实际读到或写入的数据块个数,而不是字节数。
- 交换数据比较频繁的情况下最好不要用fscanf()和fprintf()
- fseek()函数一般用于二进制文件