当我们写一个通讯录的时候,我们总是在重新打开的时候输入信息,退出时信息删除,那么我们能不能把通讯录写入文件,这样方便我们读写内容,所以我们用到了文件。所以我们先来了解什么是文件:
包括源程序文件(后缀为.c),目标文件(后缀为.obj),可执行程序(后缀为.exe)
文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件, 或者输出内容的文件。
每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息,这些信息保存在一个结构体变量中,该结构体类型由系统声明的,取名为FILE。例如,VS2023中的定义如下:
创建一个文件,系统都会自动创建这样一个结构的变量,并补充其中的信息,我们通常用一个FILE的指针来维护这个结构体变量。下面给出创建结构体指针变量的方法:
FILE* pf;//文件指针变量
定义pf是一个指向FILE类型数据的指针变量。可以使pf指向某个文件的文件信息区(也就是FILE结构体)。通过文件指针变量能够找到与它关联的文件。
文件在读写之前要先打开文件,在使用结束之后应该关闭文件。
在编写程序的时候,在打开文件的同时,都会返回一个FILE*的指针变量指向该文件,也相当于建立了指针和文件的关系。
ANSIC 规定使用fopen函数来打开文件,fclose来关闭文件。
//打开文件
FILE * fopen ( const char * filename, const char * mode );
//关闭文件
int fclose ( FILE * stream );
具体使用如下:
int main()
{
FILE* pf = fopen("data.txt", "w");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
打开文件后,将会在目标文件夹下创建data.txt文件。文件有许多种打开方式,这里用的是只写(“w”):为了输出数据,打开一个文本文件,若文件不存在,将创建一个文件。在关闭文件后,要将文件指针置为空,防止野指针现象。
C库函数fputc函数把参数char指定的字符(一个无符号字符)写入到指定的流 stream 中,并把位置标识符往前移动,相当于把字符写入文件中。
int fputc(int char, FILE *stream)
实际应用如下:
int main()
{
FILE* pf = fopen("data.txt", "w");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//读文件
fputc('a', pf);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
C 库函数fgetc函数从指定的流 stream 获取下一个字符(一个无符号字符),并把位置标识符往前移动,值得注意的是它的返回值是int,所以我们要输出到屏幕上时候,要在打印时候把int转化为char,才能打印出字符。
int fgetc(FILE *stream)
实际应用如下:
int main()
{
FILE* pf = fopen("data.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
int a=fgetc(pf);
printf("%c\n", a);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
fputs和fputc几乎一样,不过从一个字符变为可以接收一行字符串。
int main()
{
FILE* pf = fopen("data.txt", "w");
if (pf == NULL)
{
perror("fopen");
return 1;
}
fputs("abcdef", pf);
//int a=fgetc(pf);
//printf("%c\n", a);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
C 库函数fgets从指定的流 stream 读取一行,并把它存储在 str 所指向的字符串内。当读取 (n-1) 个字符时,或者读取到换行符时,或者到达文件末尾时,它会停止,具体视情况而定。
char *fgets(char *str, int n, FILE *stream)
fgets多了2个参数,一个是读取到的字符串储存的位置,一个是读取的字符个数。
int main()
{
FILE* pf = fopen("data.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//fputs("abcdef",pf);
char str[50]={0};
int a=fgets(str,7,pf);
puts(str);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
前面介绍的函数都是顺序读写,下一次读入的内容将在本次偏移量后,是顺序读写,接下来我们介绍的是随机读写,将改变指针的位置。
根据文件指针的位置和偏移量来定位文件指针。设置流 stream 的文件位置为给定的偏移 offset,参数 offset 意味着从给定的 whence 位置查找的字节数。如果成功,则该函数返回零,否则返回非零值。
int fseek(FILE *stream, long int offset, int whence)
int main()
{
FILE* pf = fopen("data.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//读文件
//定位文件指针到f
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
fseek(pf, -3, SEEK_CUR);
ch = fgetc(pf);
printf("%c\n", ch);
fclose(pf);
pf = NULL;
return 0;
}
返回文件指针相对于起始位置的偏移量。
long int ftell ( FILE * stream );
让文件指针的位置回到文件的起始位置。
void rewind ( FILE * stream );