本篇主要介绍c语言中关于文件的一些操作和用法
在正常运行程序过程中,在程序运行过程中产生的文件数据最后会在程序结束时一并销毁,那么如何把这些信息存储起来,或者如何从文件中读入一些信息存起来?这时候就用到了文件的相关操作
这样做可以把数据直接放在电脑的硬盘上,做到了数据的持久化
一般来说文件说的就是在磁盘上的文件
在程序设计中,我们把文件分为两类,一类是程序文件,一类是数据文件
程序文件就是我们见到的.c文件,或者是.obj文件,或者是.exe文件都属于程序文件
数据文件就是指的是程序运行过程中产生数据的这些文件,在介绍文件的相关功能就是要把信息输出到磁盘上,需要的时候再把这些文件从磁盘上读入到程序中,这个过程就是本篇要探讨如何实现的
首先要引入的关键概念就是文件类型指针和文件指针
当我们要使用一个文件的时候,就会在内存中开辟一个对应的文件信息区,用来存储相关文件的信息,而这些信息是被存储在一个结构体当中的,在c语言中就对这个结构体有具体的定义,c语言把它定义为FILE,在vs中,对FILE有如下所示的具体定义:
struct _iobuf
{
char *_ptr;
int _cnt;
char *_base;
int _flag;
int _file;
int _charbuf;
int _bufsiz;
char *_tmpfname;
};
typedef struct _iobuf FILE;
由此可见,实际上在c语言中就是定义了一个结构体,结构体中包含文件所需的各类成员,再把整个结构体重命名,重命名为FILE
于是当我们要进行创建一个文件信息的时候就可以借助这个文件指针进行文件的维护,这样可以更加的方便,于是就有下面的这行写法
FILE* pf;//文件指针变量
定义的这个pf就是一个指向FILE类型数据的指针变量,可以使pf指向某个文件的信息区,通过这个文件信息区的信息就可以访问该文件,也就是说,通过文件指针变量就能够找到和它相关联的文件
介绍完文件指针就可以介绍文件的打开和关闭的操作了
在c语言中,对文件的操作常常分为三部 打开文件 操作文件 关闭文件
那么首先我们就先学习一下文件的打开和关闭
在c标准中,有这样的函数,fopen用来打开文件,fclose用来关闭文件
//打开文件
FILE * fopen ( const char * filename, const char * mode );
//关闭文件
int fclose ( FILE * stream );
下面通过一个例子进行文件的打开和关闭的相关操作
#include
int main()
{
//文件的打开
FILE* pf = fopen("test.txt", "w");
if (pf == NULL)
{
perror("fopen\n");
return 1;
}
//进行文件的相关操作
fputs("打开文件成功!\n",pf);
//关闭文件
fclose(pf);
return 0;
}
运行结果如下所示
由此可见,确实在本地的磁盘内会创建一个test.txt文件,并且会在文件中保存代码中所要求保存的相关信息
代码中的fputs函数稍后会进行解释
在一段程序中想要把一段信息存储到磁盘文件中,那么就必然少不了函数,只有通过函数就能把信息放到磁盘文件中
下面是一些读写函数
fgetc
该函数是从外部的文件中读取一个字符到程序中,我们可以写下面的程序进行验证
假设test.txt文件中存放下面的信息
那么我们写下面的程序语句段
#include
int main()
{
//打开文件
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen\n");
return 1;
}
//对文件进行操作
char ch = fgetc(pf);
printf("%c\n", ch);//a
ch = fgetc(pf);
printf("%c\n", ch);//b
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
下面对程序进行分析,首先打开文件,在本地要打开的文件中已经提前存储好了abcdef,于是当我们调用fgetc函数时,就会在本地文件中读取一个字符,把它存储在我们定义好的变量ch中
接着再把ch进行打印输出即可把信息输出到屏幕上
从这段代码中可以发现一个现象,当读取完字符a后,指针会直接指向b字符,等待下一个fgetc命令就可以直接读取b字符,关于指针指向的问题后续会有相关函数进行介绍
由此可见,fgetc只能读取一个字符
fputc
和fgetc一样,是把一个字符输出到本地文件中,同样也是只能输出一个字符
用代码实现如下所示
#include
int main()
{
//打开文件
FILE* pf = fopen("test.txt", "w");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//对文件进行操作
fputc('a', pf);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
fgets/fputs
相较于fgetc/fputc来说,它可以把字符串进行交互
代码实现如下:
//对文件的写入
#include
int main()
{
FILE* pf;
//打开文件
pf = fopen("text1.txt", "w");
if (pf == NULL)
{
perror("fopen:");
return 1;
}
//操作文件
char arr[] = "helloworld";
fputs(arr, pf);
fclose(pf);
return 0;
}
//把文件进行输出
#include
int main()
{
FILE* pf;
//打开文件
pf = fopen("text1.txt", "r");
if (pf == NULL)
{
perror("fopen:");
return 1;
}
//操作文件
char str[20];
fgets(str, 20, pf);
printf("%s", str);
fclose(pf);
return 0;
}
scanf是针对标准输入流(stdin)的格式化输入函数
printf是针对标准输出流(stdout)的格式化输出函数
fscanf是针对所有输入流的格式化输入函数
fprintf是针对所有输出流的格式化输出函数
sscanf是把字符串转换为格式化的数据
sprintf是把格式化的数据转换成字符串
fseek函数是根据文件指针的位置和偏移量来定位文件指针
用代码展示功能如下:
#include
int main()
{
FILE* pf;
//打开文件
pf = fopen("test.txt", "w");
if (pf == NULL)
{
perror("fopen;");
return 1;
}
//操作文件
char ch[] = "abcdef";
fputs(ch, pf);
//关闭文件
fclose(pf);
pf = NULL;
FILE* pf2;
pf2 = fopen("test.txt", "r");
if (pf2 == NULL)
{
perror("fopen:");
return 1;
}
//操作文件
printf("%c\n", fgetc(pf2));//读取a
printf("%c\n", fgetc(pf2));//读取b,此时指向c
fseek(pf2, -1, SEEK_CUR);//把文件指针从当前位置向左移动一位
printf("%c\n", fgetc(pf2));//此时文件指向b,输出就是b
fseek(pf2, 0, SEEK_SET);//把文件指针指向开始
printf("%c\n", fgetc(pf2));
//关闭文件
fclose(pf2);
pf2 = NULL;
return 0;
}
返回的是文件指针相对于起始位置的偏移量,和上述函数类似
让文件指针的位置回到文件的起始位置,和fseek功能较为相似