各位朋友们,大家好啊,今天我要分享的是关于文件操作方面的知识。
文章目录
为什么会有文件操作
那么大家可能会问:为什么会有文件操作呢?前面我们可能都了解了通讯录,我们知道当我们使用通讯录的时候我们可以添加联系人,也可以删除联系人,但是当我们退出程序之后下次再进来的时候,我们要想看看通讯录里面有那些联系人,我们打开通讯录发现里面是空的,这是为什么呢?因为我们这种通讯录实在内存上操作的,当我们关闭程序或者关机的时候,这些内存就会被释放掉了,那么我们想要下次打开通讯录的时候,里面的内容还在的话,我们就需要使用文件来操作了。
什么是文件
文件通常是指磁盘上的文件,就像我们平时购买电脑的时候我们可能会买16+512的,这个16通常是指运行内存,我们写代码的时候通常使用的就是这个内存,而我们安装QQ、微信啊这些就是安装在磁盘上的,这些数据不会随着你电脑关机或者没电的时候而消失,他会一直存在,除非你故意删除或者磁盘损坏。所以我们使用文件来操作可以将数据存储在磁盘上保存。
文件又分为程序文件文件和内存文件。他们分类的依据是根据功能来分类的,不知道你们是否发现了,当我们写了一个代码并编译运行的时候,我们可以在我们项目的文件路径下发现.obj后缀和.exe后缀的文件,这些等等都属于程序文件,而当我们程序运行的时候读取的文件称为数据文件。
那么我们知道了什么是文件以及使用文件的好处了之后,我们来学习怎样进行文件操作。
文件操作
文件指针
每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名字,文件状态及文件当前的位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是由系统声明的,取名FILE。也就是说我们需要使用FILE来找到文件的地址,并对其进行相关操作。其实这就跟普通指针差不多,就像int* p = &a,一样*说明他是一个指针变量,而int说明这个指针指向的是int类型的数据,FILE也是如此。
文件的打开与关闭
当我们使用文件的时候我们需要在知道使用的步骤,就像我们想要在冰箱里面拿东西一样,我们首先需要打开冰箱,然后我们可以从冰箱里面拿出东西也可以往冰箱里面放东西,我们进行文件操作的时候也是先打开文件,然后进行相关操作,最后就是关闭文件。
fopen(打开文件)
FILE * fopen ( const char * filename, const char * mode );
const char* filename是我们要打开的文件地址,const char* mode是我们以怎样的形式打开。
fclose(关闭文件)
int fclose ( FILE * stream );
FILE * stream是我们需要关闭的文件地址,这里我们需要注意的是fclose并不会将要关闭的文件置为NULL,所以我们需要手动置空。
接下来我们就来看看有哪些打开文件的方式吧。
打开文件的方式
我们在使用的时候可以根据需要以不同的方式打开。我们举个例子:
首先我们在我们的项目路径下创建一个test.txt文档,用来做测试。
然后我们在这个文档里面写入内容。
#include<stdio.h>
int main()
{
//打开文件
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
}
//进行相关文件操作
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
文件的顺序读写
这里的流是什么意思呢?其实这个流只是一个抽象概念,就像一条河流,当我们需要灌溉农田的时候我们就可以用抽水机来抽取。我们的键盘和屏幕实际上也是一个文件,我们的电脑从键盘中读取数据,然后将数据显示到屏幕上,键盘也叫标准输入流(stdin),屏幕叫做标准输出流(stdout)。
那么我们来举几个例子来看看这写函数是什么作用吧。
fgets函数
char * fgets ( char * str, int num, FILE * stream );
#include<stdio.h>
int main()
{
//打开文件
FILE* pf = fopen("test.txt", "r");
char arr[10] = { 0 };
if (pf == NULL)
{
perror("fopen");
return 0;
}
//进行相关文件操作
fgets(arr, 5, pf);
printf("%s", arr);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
虽然我们在这里想要读取5个元素,但是其实只读取了4个元素,因为最后一个元素要读取’\0’。
fputc函数
int fputs ( const char * str, FILE * stream );
#include<stdio.h>
int main()
{
FILE* pf = fopen("test.txt", "w");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//写文件
//把26个字母写到文件中
int i = 0;
for (i = 0; i < 26; i++)
{
fputc('a'+i, pf);
}
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
fgets函数
char * fgets ( char * str, int num, FILE * stream );
fgets可以读取一行的数据
#include<stdio.h>
int main()
{
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//读
char arr[20];
fgets(arr, 5, pf);
printf("%s\n", arr);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
fputs函数
fputs写一行的数据
int fputs ( const char * str, FILE * stream );
#include<stdio.h>
int main()
{
FILE* pf = fopen("test.txt", "w");
if (pf == NULL)
{
perror("fopen");
return 1;
}
fputs("hello bit", pf);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
fprintf函数
int fprintf ( FILE * stream, const char * format, ... );
后面的省略号说明你自己可以定义长度。
#include<stdio.h>
struct S
{
int n;
float f;
char arr[20];
};
int main()
{
struct S s = { 100, 3.14f, "zhangsan" };
//打开文件
FILE* pf = fopen("test.txt", "w");
if (NULL == pf)
{
perror("fopen");
return 1;
}
//写文件
fprintf(pf, "%d %f %s\n", s.n, s.f, s.arr);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
fscanf函数
int fscanf ( FILE * stream, const char * format, ... );
#include<stdio.h>
struct S
{
int n;
float f;
char arr[20];
};
int main()
{
struct S s = {0};
//打开文件
FILE* pf = fopen("test.txt", "r");
if (NULL == pf)
{
perror("fopen");
return 1;
}
//读文件
fscanf(pf, "%d %f %s", &(s.n), &(s.f), s.arr);
printf("%d %f %s\n", s.n, s.f, s.arr);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
那么前面的都是顺序读写,但是当我们想要在任意位置写的时候我们又该怎么办呢?
我们这就得用到fseek函数和ftell函数了,这两个函数可以随机读写文件。
文件的非顺序读写
fseek函数
int fseek ( FILE * stream, long int offset, int origin );
stram还是我们需要读取的文件的地址,offset 是相对于origin的偏移量,origin有三种不同的形式。SET表示文件的开始位置,CUR表示文件指针的当前位置,END表示文件的结尾。
#include<stdio.h>
int main()
{
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen file");
return 1;
}
for (int i = 0; i < 5; i++)
{
fgetc(pf);
}
//现在pf文件指针已经向后移动了5个字节,现在我们想要读取的元素是b,b与文件首元素的地址的偏移量是1
fseek(pf, 1, SEEK_SET);
int a = fgetc(pf);
printf("%c", a);
fclose(pf);
pf = NULL;
return 0;
}
ftell函数
long int ftell ( FILE * stream );
ftell函数返回的是你当前的文件指针与文件开始的地址处的偏移量,这里我就不需要过多解释了。
rewind函数
void rewind ( FILE * stream );
这个函数的作用是让文件指针回到文件的起始位置
二进制读写
fwrite函数`
fwrite函数是针对二进制来说的,他写入的形式是以二进制来写的。
size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );
这个函数返回的是你写入的字符的个数,参数一个是ptr,代表的是从哪写入,一个是size,表明要写入的内容的大小,count是指要写入多少个这样的内容,stream是你要写入那个文件中。
#include<stdio.h>
struct S
{
int n;
float f;
char arr[20];
};
int main()
{
struct S s = { 10,3.14f,"hello" };
FILE* pf = fopen("test.txt", "wb");
if (pf == NULL)
{
perror("fopen");
return 1;
}
fwrite(&s, sizeof(struct S), 1, pf);
fclose(pf);
pf = NULL;
return 0;
}
这样我们可能看不懂吧,因为这是以二进制的形式写入的,所以我们并不能看懂。
fread函数
size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
#include <stdio.h>
struct S
{
char name[20];
int age;
float score;
};
int main()
{
struct S s = {0};
FILE* pf = fopen("test.txt", "rb");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//读文件
fread(&s, sizeof(struct S), 1, pf);
printf("%s %d %f\n", s.name, s.age, s.score);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
结语
那么这些就是我学到的关于文件操作的只是,感谢大家的观看,如有错误,请随时订正。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/192662.html