文件操作
(1)文件的简述
在程序设计中,存在着两种文件:
- 程序文件
- 数据文件
文件都需要名称来确定其存在,文件名有一定的格式:
//文件名 = 文件路径 + 文件名主干 + 文件后缀
//举个例子:
"c:\code\test.txt"
(2)文件的打开与关闭
(0)文件的使用方式
文件有多种使用方式,我们可以通过不同的文件打开方式来实现对文件的不同使用操作
![image-20221009140558157](https://i-blog.csdnimg.cn/blog_migrate/959b72335749480800d36e303844f75a.png)
(1)文件指针
定义:通过文件指针可以找到与之相关的文件
![IMG_0615](https://i-blog.csdnimg.cn/blog_migrate/8021179b6a71414b0d146864277444f7.png)
FILE 是 C语言文件结构定义,打开文件和文件操作要用到这类结构。可以看成变量类型,用于变量声明。这个是一种数据结构类型,用来表示一个文件的相关信息,如果定义了一个文件指针,就用这个指针来指向某个文件,然后就能使用这个指针对文件来进行操作了
(2)文件打开与关闭
先介绍两个重要的函数:
![image-20221009135539188](https://i-blog.csdnimg.cn/blog_migrate/57b0372116f483b0a0de713dbc238d6b.png)
![image-20221009135616957](https://i-blog.csdnimg.cn/blog_migrate/c7936925ee1f63aa6f2a412843ac6cb6.png)
显而易见,fopen()、fclose()
这两个函数作用对立,代表着对于文件的开与关操作。
下面我们来简单介绍这两个函数的使用:
int main()
{
//打开文件
FILE *pf = fopen("c:\\code\\test.txt","w");//先声明文件名,再明确文件的使用方式
//FILE *pf = fopen("test.txt","w");这是文件的相对路径表达,上一行是绝对路径,很显然
if(pf == NULL)
{
perror("fopen");
return 1;
}//fopen()打开文件成功后会返回地址,打开失败会返回空指针,故需要检验!
//写文件
//...
//...
//...
//关闭文件
fclose(pf);
pf = NULL;//不置为空指针就会导致野指针
return 0;
}
(3)文件的读写
![IMG_0616](https://i-blog.csdnimg.cn/blog_migrate/72720c56159886c9b51a5a81c226e522.png)
对于文件的读写,我们从作用相反的函数介绍开始:
(1)fgetc & fputc
如果你学习过 getc()、putc()
那么这两个文件读写函数的理解就简单很多了
![image-20221009142836701](https://i-blog.csdnimg.cn/blog_migrate/74e9c73d3f58bc2e039e051a57804228.png)
从fputc()
开始,你可以把这个函数的作用理解为把数据从内存一个一个地写入文件
int main()
{
FILE *pf == fopen("test.txt","w");//写入操作,故是"w"
fputc('a',pf);//写入一个字符'a'
int i = 0;
for(i=0;i<26;i++)
{
fputc('a' + i,pf);
}//写入字母表
fclose(pf);
pf==NULL;
return 0;
}
![image-20221009142901609](https://i-blog.csdnimg.cn/blog_migrate/d071ee58bf758eb6a17cdbf9f5d6cd6b.png)
再来看 fgetc()
,你可以把这个函数的作用理解为把数据从文件中一个一个地读出到内存
int main()
{
//假设原先文件里存放着字母表,即 abcdefg...xyz
FILE *pf == fopen("test.txt","r");//读操作,故是"r"
int ch = fgetc(pf);//读取一个字符'a'
int i = 0;
for(i=0;i<25;i++)//已经读出过一个字符,所以再读25个就行
{
int ch = fgetc(pf);
}//读出整个字母表
ch = 0;
while((ch=fgetc(pf)) != EOF)//判断是否到文件末尾
{
printf("%c ",ch);
}//读取到文件末尾时会返回EOF,这点和 scanf()很相似
fclose(pf);
pf==NULL;
return 0;
}
(2)fgets & fputs
功能和 fgetc()、fputc()
相似,只不过这俩是一行一行地进行操作
先来看fgets()
,特点很明显:可读数据长度有限制
![image-20221009151313360](https://i-blog.csdnimg.cn/blog_migrate/3e607dc0f42c8660cf35bef9a69d23f6.png)
FILE *pf == fopen("test.txt","r");
char arr[] = "###################........####";//字符的多少决定了可读取数据的最大长度
fgets(arr,20,pf);//每次一行,可以规定读取数据的长度
printf("%s",pf);
再来看 fputs()
,这个的理解就简单很多
![image-20221009151340591](https://i-blog.csdnimg.cn/blog_migrate/add82fffa21f9dc6bd0ba9c8e80f924a.png)
//...
fputs("hello\n world\n",pf);
//...
(3)fscanf() & fprintf()
这两个函数负责的读写功能与结构体有紧密的关系,也不是很难理解
struct S
{
char name;
int age;
float score;
};
//读取操作
int main()
{
struct S s ={0};
FILE *pf =fopen("test.txt","r");
if(pf == NULL)
{
perror("fopen");
return 1;
}
fscanf(pf,"%s %d %f",s.name,&(s.age),&(s.score));
printf("%s %d %f",s.name,s.age,s.score);
fclose(pf);
pf==NULL;
return 0;
}
//写入操作
/*int main()
{
struct S s ={张三 16 95};
FILE *pf =fopen("test.txt","w");
if(pf == NULL)
{
perror("fopen");
return 1;
}
scanf("%s %d %f",s.name,s.age,s.score);
fclose(pf);
pf==NULL;
return 0;
}
(4)fread() & fwrite()
这两个函数功能是:二进制地读写
![image-20221009153857511](https://i-blog.csdnimg.cn/blog_migrate/d738aabec269b2d5108a3da7b6c59bed.png)
//......
FILE *pf = fopen("test.txt","rb");//由于是二进制的读写,所以声明"rb"
//......
fread(&s,sizeof(s),1,pf);
//......
![image-20221009153919031](https://i-blog.csdnimg.cn/blog_migrate/7d7bf753674928caf8a339decc34e72f.png)
struct S s ={张三 16 95};
FILE *pf = fopen("test.txt","rw");
//...
fwrite(&s,sizeof(s),pf);
(4)简单补充知识
对于任何一个C语言程序,只要运行起来,就默认打开3个流:
stdin
- 标准输入流 - 键盘stdout
- 标准输出流 - 屏幕stderr
- 标准错误流 - 屏幕