C语言文件基本操作
什么是文件
与普通文件载体不同,文件是以硬盘为载体存储在计算机上的信息集合,文件可以是文本文档、图片、程序等等。文件通常具有点+三个字母的文件扩展名,用于指示文件类型(例如,图片文件常常以KPEG格式保存并且文件扩展名为.jpg)。
将数据放入文件中,相比代码程序中堆栈上的数据,其优点在于可以随时做到需要时添加、舍弃时删除,数据可以持久化。
文件分类:
文件一般讲两种:程序文件和数据文件;
程序文件:
包括源程序文件(后缀为.c),目标文件(windows环境后缀为.obj),可执行程序(windows环境后缀为.exe)。
数据文件:
包括程序运行时所读写的数据。本篇所涉及的就是数据文件。
文件的使用
文件的操作一般分三步:1.打开文件;2.读/写;3.关闭文件;
文件指针
想要对文件进行操作,“文件指针”就是一个关键桥梁(亦名:文件类型指针);
底层原理:每个被使用的文件,都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如:文件名、文件状态、文件位置等),这些信息被保存到一个结构体中,系统为其声明为FILE,每当打开一个文件的时候,系统就会根据情况自动创建一个FILE结构的变量,并且通过FILE*的指针来维护这个结构。
文件指针的使用:
FILE* pf;
定义一个文件指针变量pf,它可以指向某个文件的文件信息区,通过其即可访问到该文件。
文件的打开和关闭
在打开文件的同时,都会返回一个FILE*的指针变量指向该文件,也相当于建立了指
针和文件的关系。
fopen() —— 打开文件; FILE * fopen ( const char * filename, const char * mode ); fclose() —— 关闭文件; int fclose ( FILE * stream );
文件的使用方式:
按常用序:
文件的顺序读写:
以上结合起来实例:
#include<stdio.h> #include<string.h> #include<errno.h> int main() { FILE* pf= fopen("test.txt", "w+"); if (pf == NULL) { printf("%s\n", strerror(errno)); return; } //输入一个字符 fputc('a', pf); //用完关闭文件 fclose(pf); pf = NULL; return 0; }
如图示:在源文件所在目录下,原本没有test.txt文件,是w+创建了这个新的文件,并写入一个字符a
1.写入一个字符:
//写文件 fputc('a', pf);
2.读取一个字符:
//读取一个字符 int ch = fgetc(pf); if (ch != EOF) { printf("%c\n", ch); }
3.连续每次读取一个字符:
//文件中有abcdefg int ch = fgetc(pf); printf("%c\n", ch); //a ch = fgetc(pf); printf("%c\n", ch); //b ch = fgetc(pf); printf("%c\n", ch); //c ch = fgetc(pf); printf("%c\n", ch); //d
4.覆盖并写入一行数据:
fputs("hello world", pf);
注意:这里fputs函数虽然是整行写入,但会覆盖掉原始数据
5.读取指定长度的数据:
//定一一个数组 char arr[10] = { 0 }; fgets(arr, 5, pf); //将所读取的数据放入arr中 printf("%s\n", arr);
6.将结构体信息写入文件中:
这里的结构体信息就是格式化的,那么就需要fprintf()函数了
#include<stdio.h> typedef struct S { char name[10]; int age; }Peo; int main() { FILE* pf = fopen("test.txt", "w"); if (pf != NULL) { Peo p = { "zhangsan", 18 }; fprintf(pf, "%s %d\n", p.name, p.age); fclose(pf); pf = NULL; } return 0; }
7.读取文件信息到结构体变量中:
#include<stdio.h> typedef struct S { char name[10]; int age; }Peo; int main() { FILE* pf = fopen("test.txt", "r"); if (pf != NULL) { Peo p = { 0 }; fscanf(pf, "%s %d", p.name, &p.age); printf("%s %d", p.name, p.age); fclose(pf); pf = NULL; } return 0; }
8.二进制写入文件:
- size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream );
#include<stdio.h> #include<string.h> #include<errno.h> typedef struct S { char name[10]; int age; }Peo; int main() { FILE* pf = fopen("test.txt", "wb+"); if (pf != NULL) { Peo p = { "lisi", 19}; fwrite(&p, sizeof(Peo), 1, pf); fclose(pf); pf = NULL; } return 0; }
9.读取二进制文件信息:
size_t fread( void *buffer, size_t size, size_t count, FILE *stream );
#include<stdio.h> typedef struct S { char name[10]; int age; }Peo; int main() { FILE* pf = fopen("test.txt", "rb+"); if (pf != NULL) { Peo p = { 0 }; fread(&p, sizeof(Peo), 1, pf); printf("%s %d\n", p.name, p.age); fclose(pf); pf = NULL; } return 0; }
10.sscanf()函数、sprintf()函数:
这两个函数虽然和文件操作关系不大,但是容易与文件操作函数混淆;
- sscanf()函数:
- int sscanf( const char *buffer, const char *format [, argument ] ... );
- 将一个字符串转化为格式化数据;
#include<stdio.h> typedef struct S { char name[10]; int age; }Peo; int main() { //定义一个字符串 char buffer[] = { "zhansan 19" }; //定义一个结构但不赋值 Peo p = { 0 }; sscanf(buffer, "%s %d", p.name, &p.age); return 0; }
- sprintf()函数:
int sprintf( char *buffer, const char *format [, argument] ... );
将一个格式化数据转化为字符串;
#include<stdio.h> typedef struct S { char name[10]; int age; }Peo; int main() { //定义一个结构 Peo p = { "zhangsan",19}; //定义一个字符串 char buffer[50] = { 0 }; sprintf(buffer, "%s %d\n", p.name, p.age); return 0; }
文件读取结束判定
feof()函数:
该函数被许多人错误用来判断文件是否读取结束,其实它的作用是判断文件读取结束的原因;
文件读取结束有两种情况:1.读取过程中出现异常; 2.读取到文件末尾;
要找出文件读取是哪个原因,就分为以下情况:
文本文件:
如果用 fgetc() 读取,要判断 feof() 的返回值是否为EOF;
如果用 fgets() 读取,要判断 feof() 的返回值是否为NULL(0);
二进制文件:
都是使用 fread() 读取,要判断其返回值与指定读取个数的大小,如果小于实际要读的个数,就说明发生读取异常,如果等于实际要读的个数,就说明是因读取成功而结束;
对于读取异常的判断,我们考虑判断 ferror() 函数的返回值:
若ferrror()为真——异常读取而结束;
若feof()为真——正常读取到尾而结束;
文本文件的判断:
#include<stdio.h> #include<string.h> #include<errno.h> int main() { FILE* pf = fopen("test.txt", "r"); if (pf == NULL) { perror("fopen is failed !"); return; } int c = 0; //由于要检查EOF——EOF本质是0——所以是int while (c = fgetc(pf) != EOF) { putchar(c); } //直到while不执行了—读取结束了—判断是什么原因结束的 if (ferror(pf)) { printf("读取中出现错误\n"); } else if (feof(pf)) { printf("读取到文件尾\n"); } fclose(pf); pf = NULL; return 0; }
转载:https://blog.csdn.net/m0_65190367/article/details/126682477
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)