文件操作:
控制台输出的结果会随着程序的结束、控制台的关闭而消失,那么如果想要保留输出结果,实现数据的持久化,该如何做呢?
数据的持久化,可以通过把数据保存在磁盘或存放到数据库中,而文件的数据就是存储在磁盘上,因而可以通过将数据写入文件来实现数据的持久化
将数据写入文件保存,这一过程称为序列化过程(写数据)
将文件中的数据读取出来,这一过程称为反序列化过程(读数据)
使用关键字FILE定义文件指针,文件指针指向一个文件
文件操作函数的返回值为一个指针,用定义的文件指针来接收这个返回值
#include<stdio.h>
int main()
{
FILE*fp; //定义一个文件指针
fp=fopen("test.txt","r"); //调用fopen文件打开函数,“r”表示以只读形式打开
//文件指针fp接收返回值,打开失败返回一个空指针NULL
if(fp==NULL) //对文件指针进行判空,若为空,则打开文件失败
{
printf("OPen File Error"\n);
return;
}
fclose(fp); //调用fclose文件关闭函数关闭该文件
}
文件操作相关函数
- fopen(文件打开函数)
FILE*fopen(const char*filename,const char *mode)参数为文件名和一个操作码,返回值为一个文件指针
注:程序运行时,文件查找的默认路径是从当前目录进行查找,如果当前目录下没有这个文件,那么程序就找不到了,所以应当告知程序该文件所在的路径
例如:fp=fopen("C:\\Users\\source\\repos\\Test_文件操作\Test.c","r")
注意:路径中存在 '\',使用转义字符\将'\'转义,
常用操作码有:
"r" 只读,可以从中读取数据
"w" 只写,可以向其中写入数据,如果该文件不存在,将创建该文件
"a" 追加,向文本文件尾添加数据
"rb" b表示binary,以二进制形式打开,fscanf,读取
"wb" 以二进制形式打开,fprintf,写入
"ab" 以二进制形式打开,向尾部添加数据
- fclose(文件关闭函数)
int fclose(FILE*stream)参数为一个文件指针,成功关闭返回一个0,否则返回一个EOF,可看做是-1
- fprintf(文件输出函数) /(文件写入函数)
int fprintf(FILE *stream,......)参数相较于printf只是多了一个文件指针
文件写入数据时,会将原有数据清除,如果想要在原有数据基础上写入,使用"a"操作码
- fscanf(文件输入函数)/(文件读取函数)
int fscanf(FILE *stream,......)参数相较于scanf同样只是多了一个文件指针
#include<stdio.h>
#include<assert.h>
#pragma warning(disable:4996)
int main()
{
FILE* fp1 = fopen("Test.txt", "w"); //以写操作打开一个文件Test.txt
//若该文件不存在将会创建一个Test.txt
assert(fp1 != NULL);//判空
int ar[10] = { 0 };
for (int i = 0; i < 10; ++i)
{
ar[i] = i;
fprintf(fp1, "%d ", ar[i]); //将数组内容打印/写入到Test.txt文件中
}
fclose(fp1);//关闭文件
}
- fgetc(文件字符获取函数)
int fgetc(FILE* stream)参数为一个文件指针,用于从文件中获取一个字符,返回值为该字符,以int类型返回
- fputc(文件字符打印函数)
int fputc(int c,FILE *stream)参数为一个int类型的字符,和一个文件指针,将该字符打印到文件指针指向的文件中
#include<stdio.h>
#include<assert.h>
#pragma warning(disable:4996)
int main()
{
FILE* fpIn = fopen("Test.c", "r"); //将当前文件打开
FILE* fpOut = fopen("Copy.txt", "w"); //以写操作打开一个Copy.txt文件
assert(fpIn != NULL && fpOut != NULL);//判空
char ch = fgetc(fpIn); //从Test.c中读取一个字符
while (ch != EOF) //循环获取字符
{
fputc(ch, fpOut);//将字符打印到Copy.txt文件中
ch = fgetc(fpIn);
}
fclose(fpIn);//关闭文件
fclose(fpOut);
}
- fgets(文件字符串获取函数)按行读取,一行如果字符数超过n,多次读取
char *fgets( char *string, int n, FILE *stream )参数为一个一维字符数组用来存放获取的字符串,一个整型n,告诉函数获取多少个字符,和一个文件指针指向要获取的文件,返回值为一个字符指针
- fputs(文件字符串打印函数)
int fputs( const char *string, FILE *stream )参数为一个一维数组,数组中存放的要打印的字符,和一个文件指针,指向要打印的文件
#include<stdio.h>
#include<assert.h>
#pragma warning(disable:4996)
int main()
{
FILE* fpIn = fopen("Test.c", "r"); //打开当前文件
FILE* fpOut = fopen("Copy.txt", "w"); //以写操作打开一个Copy.txt文件
assert(fpIn != NULL && fpOut != NULL);//判空
char buf[128] = { 0 }; //定义一个字符数组作为缓冲区接收fgets获取的字符
char* pc = fgets(buf, 64, fpIn);//定义一个字符指针接收fgets的返回值
while (pc != NULL) //循环获取Test.c的字符内容
{
fputs(buf, fpOut);//fputs打印获取到的字符内容
pc = fgets(buf, 64, fpIn);
}
fclose(fpIn);//关闭文件
fclose(fpOut);
}
- fread(二进制文件读取函数)将文件数据以二进制的形式,即以字节为单位读取,越过编码方式,从指定文件中读取数据
size_t fread( void *buffer, size_t size, size_t count, FILE *stream )
参数为一个一维数组空间void *buffer(任意类型都可),作为缓冲区,接收从文件中读取出来的数据
size_t size是一次要读取的字节数,size_count则表示读取的次数
FILE*stream是指向要读取的文件的文件指针,返回值为一个无符号整型,表示实际读取到的字节数
- fwrite(二进制文件写入函数)将文件数据以二进制的形式,即以字节为单位写入,越过编码方式,写入到指定文件中
size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream )
参数为一个一维数组空间void *buffer(任意类型都可),是fread写入数据的那个缓冲区,fwrite从其中读取数据
size_t size是一次要读取的字节数,size_count则表示读取的次数
FILE*stream是指向要写入的文件的文件指针,返回值为一个无符号整型,表示实际写入到的字节数
Tips:以二进制形式读取和写入的特性使得这两个函数可以实现任意格式文件的拷贝
#include<stdio.h>
#include<assert.h>
#pragma warning(disable:4996)
int main()//二进制形式的读取使得可以拷贝任何格式的文件,以下就是拷贝一个pdf文件
{
FILE* fpIn = fopen("license.pdf", "rb"); //以二进制只读形式打开文件
FILE* fpOut = fopen("Copy.pdf", "wb"); //以二进制写操作打开文件
assert(fpIn != NULL && fpOut != NULL); //判空
char buf[128] = { 0 }; //定义一个缓冲区
int ret = 0; //定义一个ret接收fread的返回值,ret的值为实际读取到的字节数
ret = fread(buf, sizeof(char), 128, fpIn);//fread,从fpIn读取数据到缓冲区buf,每次读取一个字节,读取128次,
while(ret!=0) //ret!=0说明还能读取到数据,那就一直读取下去
{
fwrite(buf, sizeof(char), ret, fpOut); //将数据从缓冲区buf写入到fpOut指向的文件中,每次写入一个字节,写入128次
ret=fread(buf, sizeof(char), 128, fpIn);//继续读取
}
fclose(fpIn);//关闭文件
fclose(fpOut);
}