本文对C语言操作文件部分充分演示了(具体看文章目录),基本的函数操作都用最简单的方式去展示,先看代码再看总结。
看懂文章要求懂结构体
以下内容如果读者不喜欢,您也可以按照这个目录去学习(是完整目录了),下面是学习C语言操作文件章节需要掌握的内容
操作系统以文件为单位对数据进行管理,输入输出是数据传送的过程,数据如流水一般,从某个位置流到另外一个位置,又从另外一个位置流过来,所以把输入和输出称为一种流,输入输出流
数据文件分为二进制文件和ASCII文件,ASCII文件是一种文本文件
下面是形象的比喻
ASCII文件可以用文本软件来读取,但是二进制文件一般不可以正常打开,要专用一定的软件或插件转化为显示010101数字的文本可以使其看到010101或者转为汇编语言等(.bin后缀的或者我们常看到的.jpg .doc .mp3等)
文件类型指针,其实是指向一个结构体的指针,这个结构体是FILE结构体,熟悉结构体就会很容易看懂
struct _iobuf {
char *_ptr; //文件输入的下一个位置
int _cnt; //当前缓冲区的相对位置
char *_base; //指基础位置(应该是文件的其始位置)
int _flag; //文件标志
int _file; //文件的有效性验证
int _charbuf; //检查缓冲区状况,如果无缓冲区则不读取
int _bufsiz; //文件的大小
char *_tmpfname; //临时文件名
};
typedef struct _iobuf FILE;
FILE *fp;//这是定义了一个结构体指针变量,指向了某一个文件结构体变量
//从而通过该结构体变量中的文件信息能够访问该文件
操作文件时,这个fopen和fclose是必须的使用的,下面介绍到的操作都基于您已经fopen流和文件建立关联才可以
int main(){
fopen函数('这个是文件地址','这是文件使用方式(上图)');
FILE *fp = fopen("demo.txt","r");
fclose(fp);
}
在文件打开文件后,文件默认最后一个是“EOF”为结束符(end of file)
关闭函数fclose成功返回0,否则返回EOF(-1)
字符读写大白话就是一个字符一个字符的读,和一个字符一个字符的写
#include
#include
int main(){
//fputc函数完成了后指针就会自动移到下一个位置让下面的程序继续执行
FILE *fp = fopen("demo.txt","r+");
fputc('a',fp);//完成后指针默认移到下一个位置
printf("%X\n",fp->_ptr);//1969F1 代表现在在1969F0 结构体提供的查询下一个位置的变量
fputc('b',fp);// +1
printf("%X\n",fp->_ptr);//1969F2 代表现在在1969F1这个位置
fputc('c',fp);// +1 现在在1969F2的位置
rewind(fp); //这个函数用于复位,把指针位置重置到文件开头,这个函数没有返回值(六、本文文件定位与操作中讲到)
printf("%X\n",fp->_ptr);//1969F0
char ch = fgetc(fp);//操作完成后指针也默认移到下一个位置
printf("%c"ch);//a
printf("这个是%c",fgetc(fp)); //b 操作完成后指针也默认移到下一个位置
printf("这个是%c",fgetc(fp)); //c
printf("这个是%d",fgetc(fp)); //这个是空了的EOF,返回的是-1用%d接收
fclose(fp);
return 0;
}
总结:
- fputc(‘传入单个字符’,文件类型指针),把字符写入到文件中去
- fgetc(文件类型指针)
- fputc的返回值是传入的字符,如果失败则返回EOF(-1)
- fgetc从文件读出一个字符,返回值就是字符,遇到结束符,函数返回一个文件结束标志EOF(也就是-1)
字符串的读写,读的是字符串,写的也是字符串的方式去写
int main(){
FILE *fp = fopen("demo.txt","r+");
char str[20];
fputs("woaini jiuxianglaoshuaidami",fp);//这时指针已经写到很远了
rewind(fp);//重置到文件开头
fgets(str,20,fp);//从fp绑定的文件中,读取20个字符,存到str字符串数组中
printf("%s",str);//woaini jiuxianglaos
//由于字符串长度远大于20,他被我定义得只可读20个
fclose(fp);
return 0;
}
总结:
- fputs(“字符串”,文件类型指针)
- fgets(接收字符串的数组,查看的长度,文件类型指针)
- fputs函数,可以把字符串写入到文件中,成功了返回0,失败了返回EOF(-1);
- fgets函数,成功返回数组首元素的地址,上面的数组是str,所以返回str的首地址,如果出错则返回NULL
格式化读写,毋庸置疑,就是按照一种自己定义的格式去对文件的读和写
int main(){
FILE *fp = fopen("demo.txt","r+");
char ch[20],ch2[20],ch3[20];
int year;
fprintf(fp,"%s %s %s %s %d","wo","ai","ni","ha",2020);//如果成功,则返回写入的字符总数,否则返回一个负数。
//文件查看得到wo ai ni ha 2020
rewind(fp);
fscanf(fp,"%s %s %s %d",ch,ch2,ch3,&year);//如果成功,该函数返回成功匹配和赋值的个数。如果到达文件末尾或发生读错误,则返回 EOF。
printf("%s\n",ch);//wo
printf("%s\n",ch2);//ai
printf("%s\n",ch3);//ni
printf("%d\n",year);//0
return 0;
}
总结:
- fprintf(文件类型指针,格式字符串,输出列表)
- fprintf如果成功,则返回写入的字符总数,否则返回一个负数
- fscanf(文件类型指针,格式字符串,输入列表)
- fscanf 如果成功,该函数返回成功匹配和赋值的个数。如果到达文件末尾或发生读错误,则返回 EOF(-1)。
int main(){
FILE *fp = fopen("demo.txt","r+");
//frwrite是写数据,把数据写入文件中
//fread 是读数据,把文件数据读到数组中
char buffer[20];
char str[20] = "wo zhi xiang kankan";
fwrite(str,5,4,fp);//这个是说明,写5个字节,写4次(相当于写20个字符
rewind(fp);
fread(buffer,5,4,fp);//读5个字节,读4次,相当于也是20个字符
printf("%s\n",buffer); //wo zhi xiang kankan
return 0;
}
总结:
- fwrite(buffer,size,count,fp) buffer是一个指针,是指输出数据的地址(可以是文件的地址);
- fread(buffer,size,count,fp) buffer是一个指针,是指读出数据的地址,上面代码写的是一个字符数组
- count是次数,size是字节 fp是文件类型指针
读写函数什么时候用ASCII输入输出流呢,什么时候用二进制流?
阅读了其他博主的文章与书本,我了解并总结到
当用ASCII对磁盘文件读写的时候,虽然容易理解,但是计算机只认识二进制,所以输入的时候要转为二进制,输出的时候又要从二进制转为字符,时间开销大。如果是内存和磁盘经常打交道的情况下,尽量使用fread 和 fwrite
功能是改变文件的位置指针
起始点(有三个):(可以用英文写,也可以用数字写)----> 文件开头 SEEK_SET 0 , 文件当前位置 SEEK_CUR 1 , 文件末尾SEEK_END 2
FILE *fp = fopen("demo.txt","w+");
fseek(fp,4,SEEK_SET);//0
fwrite("我很好",3,2,fp);// 我很好(前面有四个空格)
FILE *fp = fopen("demo.txt","w+");
fseek(fp,1,SEEK_CUR);//1
fwrite("我很好",3,2,fp);// 我很好(当前位置是开头,所以前面有一个空格)
FILE *fp = fopen("demo.txt","w+");
fseek(fp,-1,SEEK_CUR);//1
fwrite("我很好",3,2,fp);// 我很好(当前位置是开头,所以前面有一个空格)
FILE *fp = fopen("demo.txt","w+");
fseek(fp,10,SEEK_CUR);
fseek(fp,-8,SEEK_CUR);//1 负数是左移的意思
fwrite("我很好",3,2,fp);// 我很好(前面有两个个空格)
FILE *fp = fopen("demo.txt","w+");
fseek(fp,6,SEEK_END);
fwrite("我很好",3,2,fp);// 我很好(前面有六空格)
相对于文件开头的的位移量来表示,返回值是当前位置,出错时返回-1
int main(){
FILE *fp = fopen("demo.txt","w+");
fputc('a',fp);
fputc('b',fp);
fputc('c',fp);
fputc('d',fp);
int i = ftell(fp);
printf("%d\n",i); //4
return 0;
}
把指针重置到文件开头,函数没有返回值
int main(){
FILE *fp = fopen("demo.txt","w+");
fputc('a',fp);
fputc('b',fp);
rewind(fp);
int i = ftell(fp);
printf("%d\n",i); //0
return 0;
}
int main()
{
FILE *fp;
char c;
fp = fopen("file.txt", "w");
c = fgetc(fp);
if( ferror(fp) )
{
printf("读取文件:file.txt 时发生错误1\n");//输出了
}
clearerr(fp);//在不写这句的时候,两个报错都会输出,因为ferror为非0了,但是写它,使其标志为0,后面的
//ferror变为了0,只要出现了错误标志,就一直保留。
if( ferror(fp) )
{
printf("读取文件:file.txt 时发生错误2\n");//没有输出
}
fclose(fp);
return(0);
}
以上内容如果读者不喜欢,可以按照这个目录去学习(完整目录),上面是学习C语言操作文件章节需要掌握的内容
如有错误或改进的地方,欢迎评论。谢谢您的阅读。