一:为什么要使用文件
如果没有⽂件,我们写的程序的数据是存储在电脑的内存中,如果程序退出,内存回收,数据就丢失了,等再次运⾏程序,是看不到上次程序的数据的,如果要将数据进⾏持久化的保存,我们可以使⽤⽂件。
二:什么是文件:
1.什么是文件
磁盘(硬盘)上的⽂件是⽂件
2.文件分类
(1)程序文件:
程序⽂件包括源程序⽂件(后缀为.c),⽬标⽂件(windows环境后缀为.obj),可执⾏程序(windows环境后缀为.exe)
(2)数据文件:
⽂件的内容不⼀定是程序,⽽是程序运⾏时读写的数据,⽐如程序运⾏需要从中读取数据的⽂件,或者输出内容的⽂件。
注:本部分讨论数据文件。
3.文件名:
⼀个⽂件要有⼀个唯⼀的⽂件标识,以便⽤⼾识别和引⽤。
⽂件名包含3部分:⽂件路径+⽂件名主⼲+⽂件后缀。
例如: c:\code\test.txt
为了⽅便起⻅,⽂件标识常被称为⽂件名
4.二进制文件和文本文件:
1.文本文件:
如果要求在外存上以ASCII码的形式存储,则需要在存储前转换。以ASCII字符的形式存储的⽂件
2.二进制文件:
数据在内存中以⼆进制的形式存储,如果不加转换的输出到外存的⽂件中
三:文件的打开和关闭:
1.流:
我们程序的数据需要输出到各种外部设备,也需要从外部设备获取数据,不同的外部设备的输⼊输出操作各不相同,为了⽅便程序员对各种设备进⾏⽅便的操作,我们抽象出了流的概念,我们可以把流想象成流淌着字符的河。C程序针对⽂件、画⾯、键盘等的数据输⼊输出操作都是通过流操作的。⼀般情况下,我们要想向流⾥写数据,或者从流中读取数据,都是要打开流,然后操作。
2.标准流:
(1)stdin:
标准输⼊流,在⼤多数的环境中从键盘输⼊,scanf函数就是从标准输⼊流中读取数据。
(2.)stdout:
标准输出流,⼤多数的环境中输出⾄显⽰器界⾯,printf函数就是将信息输出到标准输出
流中。
(3.)stderr:
标准错误流,⼤多数环境中输出到显⽰器界⾯。
stdin、stdout、stderr三个流的类型是: FILE* ,通常称为⽂件指针,C语⾔中,就是通过 FILE* 的⽂件指针来维护流的各种操作的。
3.文件指针:
每个被使⽤的⽂件都在内存中开辟了⼀个相应的⽂件信息区,⽤来存放⽂件的相关信息(如⽂件的名字,⽂件状态及⽂件当前的位置等)。这些信息是保存在⼀个结构体变量中的。该结构体类型是由系统声明的,取名FILE.
通过⽂件指针变量能够间接找到与它关联的⽂件。这个文件信息内容也就由该文件指针来维护。
4.文件的打开和关闭:
前言:在进行文件操作的时候,首先应该打开文件,最后应该关闭文件。
文件打开:
文件打开使用函数:fopen()
使用该函数打开文件会返回一个FILE* 的文件指针,后续相关的问案件操作可以通过该指针来维护。第一个参数是一个文件名,第二个参数是文件打开的模式。其中文件打开的方式有以下几种
文件关闭:
文件关闭使用函数:fclose()
传入文件打开函数时返回的指针就可以关闭文件。
返回值:
如果文件成功关闭,则返回零值。
失败时,返回 EOF(end of file)
代码示例:
int main()
{
//打开文件
FILE* pf = fopen("data.txt", "r");
//判断文件是否打开成功
if (pf == NULL)
{
perror("fopen");
return EXIT_FAILURE;
}
//文件操作
int cot = 0;
while (fgetc(pf) != EOF)//计算文件内字符个数。
{
cot++;
}
printf("%d", cot);
//关闭文件
fclose(pf);
pf = NULL;//记得将文件指针置为空,要不然就是野指针了。
return 0;
}
/*
个人理解:一般文件操作步骤
1.打开文件,判断文件是否打开成功
2.文件操作
3.关闭文件
4.将文件指针置为空
*/
文件操作常用函数(文件的读写操作函数)
相关函数使用代码示例:
//fgetc和fputc函数
//fgetc从流(文件指针维护的文件中取字符)
//fputc从流中放字符,
int main()
{
//打开文件
FILE* pf = fopen("data.txt", "r");//
if (pf == NULL)
{
perror("fopen");
return EXIT_FAILURE;
}
/*fputc('a', pf);//单个字符记得不要用双引号。要用单引号。
fputc('d', pf);
fputc('w', pf);
fputc('g', pf);
使用这部分代码的时候打开文件方式应该切换为"w",要不然无效代码
*/
FILE* pfgetc = fopen("data4.txt","w");
if (pfgetc == NULL)
{
perror("fopen");
return EXIT_FAILURE;//EXIT_FAILURE这个宏定义的值为1
}
int ch = 0;
while ((ch = fgetc(pf)) != EOF)//将data.txt文件的内容复制到data4.txt中
{
fputc(ch,pfgetc);
}
return 0;
}
//fputs和fgets函数
int main()
{
FILE* pf = fopen("data.txt", "r");
fputs("dafag", pf);
char ch[20] = { 0 };
fgets(ch ,10, pf);
printf("%s\n", ch);
return 0;
}
//fscanf和fprintf函数
typedef struct s {
int age;
char str[20];
int num;
}S;
/*可去掉注释自行测试查看
int main()
{
S s = { 22,"adfhgiupa",5 };
FILE* pf = fopen("data.txt", "w");
if (pf == NULL)
{
perror("fopen");
return EXIT_FAILURE;
}
fprintf(pf, "%d %s %d", s.age, s.str, s.num);
fclose(pf);
pf = NULL;
return 0;
}
*/
int main()
{
char str[20] = { 0 };
FILE* pf = fopen("data.txt", "r");
if (pf == NULL)
{
perror("fopen");
return EXIT_FAILURE;
}
fscanf(pf, "%s", str);//一直读取字符,知道遇到空格或者isspce函数判定相关的字符
printf("%s\n", str);
fclose(pf);
pf = NULL;
return 0;
}
//fread和fwrite函数(二进制读和写)
/*去掉注释测试
int main()
{
//打开文件
FILE* pf = fopen("data.txt", "r");
//判断文件是否打开成功
if (pf == NULL)
{
perror("fopen");
return EXIT_FAILURE;
}
//文件操作
char str[100] = { 0 };
fread(str, sizeof(char), 100, pf);
printf("%s\n", str);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
*/
int main()
{
//打开文件
FILE* pf = fopen("data.txt", "w");
//判断文件是否打开成功
if (pf == NULL)
{
perror("fopen");
return EXIT_FAILURE;
}
//文件操作
char str[100] = "afhlkiahgliaglaihruaer";
fwrite(str, sizeof(char), 30, pf);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
如果想测试上述代码,请包涵相关函数对应头文件。
在运行代码的时候,可找到对应同路径的文件夹查看操作的相关文件。