目录
为什么使用文件
我们在写程序的时候会发现,在程序执行的过程中,变量在内存中开辟空间,并设置值,但是程序运行结束后,内存空间就会被回收,值也并没有被存储下来,数据将会丢失。因此,我们可以使用文件来存储数据,保证在程序退出后,再运行时,数据依旧存在,让数据永久化的保存下来。
什么是文件
1.1文件
存储在磁盘(优盘)上的文件就是文件。文件分为程序文件和数据文件(从文件功能的角度来分类的)。
1.2程序文件
以.c或者.obj或者.exe等结尾的文件就是程序文件。
例如:源文件,目标文件,可执行程序等…
1.3数据文件
数据文件不一定是程序文件,而是程序运行时读写的数据,比如程序运行时需要从中读取数据的文件,或者需要输出内容的文件。数据文件又分为二进制文件和文本文件。
1.4文件名
文件名是文件的文件标识,以便用户识别和使用。文件名由三部分组成:文件路径+文件名主干+文件后缀。
例如:
c:\code\test.txt
为了方便,文件标识常被称为文件名。
二进制文件和文本文件
1.1 二进制文件:数据在内存中以二进制的形式存储,不加转换的外输到文件中。
例如:
int main()
{
FILE* pf = fopen(“test,txt”, “wb”);
if (pf == NULL)
{
perror(“fopen”);
return 1;
}
int n = 1000;
fwrite(&n, 4, 1, pf);//以二进制的形式写到文件中
fclose(pf);
pf = NULL;
return 0;
}
1.2 文本文件:
如果要求在外存上以ASCII码值的形式存储,则需要在存储前进行转换。以ASCII字符形式存储的文件就是文本文件。
int main()
{
FILE* pf = fopen(“test,txt”, “w”);
if (pf == NULL)
{
perror(“fopen”);
return 1;
}
int n = 1000;
fprintf(pf, “%d”, n);
fclose(pf);
pf = NULL;
return 0;
}
文件的打开和关闭
1.1流和标准流
我们的程序需要从外部设备中输入数据,也需要从外部设备中输出数据,因此,抽象出了流的概念。我们可以把流想象成流淌着数据的河流。
一般,我们从流里输入数据和输出数据都是需要打开流的。
1.2标准流
我们向键盘输入数据和向屏幕输出数据的时候为什么没有打开过流呢?
因为C语言在启动的时候会默认打开三个流。
- stdin 标准输入流
- stdout 标准输出流
- stderr 标准错误流
默认打开了这三个流,我们就可以使用scanf,printf函数了。
stdin
,stdout
,stderr
这三个流的类型:FILE *(通常称为文件指针)。
在C语言中,就是通过FILE *的文件指针来维护流的。
1.3文件指针
每打开一个文件,都会在内存中开辟一个文件信息区,用来存放文件信息的,文件信息区里的信息是放在结构体变量中的,是结构体类型的。该结构体类型是系统声明的,名为FILE。
文件在读写时应该先打开文件,然后再关闭文件
1.4文件的打开
在打开文件的之后,都会返回一个FILE *
类型的指针变量指向该文件,也就相当于建立了文件和指针的关系。
文件的打开需要使用fopen()
函数。
FILE * fopen ( const char * filename, const char * mode );
例如:
FILE * pf = fopen(“test.txt”,“r”);//test.txt是需要打开的文件名,r表示的是以只读的形式打开。
//返回值用FILE * 类型的指针接收。
文件的关闭需要使用fclose()
函数。
int fclose ( FILE * stream );
例如:
fclose(pf);
pf = NULL;//关闭文件后,pf还是指向的开辟的文件信息区的那一片空间,是野指针
,所以我们需要置为空。
int main()
{
//打开文件
FILE* pf = fopen("test.txt", "w");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
文件的顺序读写
1.1文件的循序读写函数介绍
1.1.1 fputc
函数
fputc
是字符输出函数。
例如:
#include<stdio.h>
int main()
{
//打开文件
FILE* pf = fopen("test.txt", "w");
if (pf == NULL)
{
perror("fopen");
return 1;
}
fputc('a', pf);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
1.1.2fgetc()
函数
fgetc
是字符输入函数。
例如:
#include<stdio.h>
int main()
{
//打开文件
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
int ret = fgetc(pf);
printf("%c\n", ret);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
1.1.3fputs()
函数
fputs()
是文本行输出函数。
int fputs( const char *string, FILE *stream );
例如:
#include<stdio.h>
int main()
{
//打开文件
FILE* pf = fopen("test.txt", "w");
if (pf == NULL)
{
perror("fopen");
return 1;
}
char arr[] = "asdfgh";
fputs(arr, pf);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
1.1.4 fgets()
函数
fgets()
是文本行输入函数。
char *fgets( char *string, int n, FILE *stream );
#include<stdio.h>
int main()
{
//打开文件
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
char arr[20] = { 0 };
fgets(arr, 5, pf);
printf("%s\n",arr);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
该函数会在末尾自动添加\0
1.1.5 fprintf()
函数
fprintf()
函数是格式输出函数
例如:
int fprintf( FILE *stream, const char *format [, argument ]…);
int main()
{
//打开文件
FILE* pf = fopen("test.txt", "w");
if (pf == NULL)
{
perror("fopen");
return 1;
}
fprintf(pf, "%d", 123);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
1.1.6fscanf()
函数
fscanf()
函数是格式化输入函数
例如:
int fscanf( FILE *stream, const char *format [, argument ]… );
int main()
{
//打开文件
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
int ret = 0;
fscanf(pf, "%d", &ret);
printf("%d\n", ret);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
1.1.7fwrite()
函数
fwrite()
函数是二进制输出函数。
例如:
size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream );
int main()
{
//打开文件
FILE* pf = fopen("test.txt", "wb");
if (pf == NULL)
{
perror("fopen");
return 1;
}
int a[5] = { 1,2,3,4,5 };
int ret = fwrite(&a, sizeof(int), 5, pf);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
1.1.8fread()
函数
fread()
函数是二进制输入函数
例如:
size_t fread( void *buffer, size_t size, size_t count, FILE *stream );
int main()
{
//打开文件
FILE* pf = fopen("test.txt", "rb");
if (pf == NULL)
{
perror("fopen");
return 1;
}
int a[5] = { 0 };
fread(a, sizeof(int), 5, pf);
for (int i = 0; i < 5; i++)
{
printf("%d ", a[i]);
}
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
文件的随机读写
1.1fseek()
函数
fseek()
函数可以根据文件指针的位置和偏移量来定位指针。
例如:
int fseek( FILE *stream, long offset, int origin );
int main()
{
//打开文件
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
fseek(pf, 2,SEEK_SET);
int ret = fgetc(pf);
printf("%c", ret);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
test.txt
文件中的内容
1.2ftell()
函数
ftell()
函数:返回文件指针相对于起始位置的偏移量
例如:
long ftell( FILE *stream );
int main()
{
//打开文件
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
fseek(pf, 2, SEEK_SET);
long ret = ftell(pf);
printf("%d ", ret);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
1.3rewind()
函数
rewind()
函数:让文件指针回到起始位置。
例如:
void rewind( FILE *stream );
int main()
{
//打开文件
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
rewind(pf);
char ret = 0;
ret = fgetc(pf);
printf("%c", ret);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
文件读取结束的判定
1.1文件结束的返回值
fgetc()
函数判断是否为EOF
fgets()
函数判断是否为NULL
1.2文件是什么原因结束的呢?
可以使用以下两个函数:
feof()
函数用来判断文件结束的原因:遇到文件末尾ferror()
函数用来判断文件结束的原因:文件发生错误
例如:
int main()
{
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
char ret = 0;
while ((ret = fgetc(pf)) != EOF)
{
putchar(ret);
}
if (feof(pf))
printf("文件结束\n");
else if (ferror(pf))
printf("文件发生错误\n");
fclose(pf);
pf = NULL;
return 0;
}
文件缓冲区
ANSIC 标准采⽤“缓冲⽂件系统” 处理的数据⽂件的,所谓缓冲⽂件系统是指系统⾃动地在内存中为程序中每⼀个正在使⽤的⽂件开辟⼀块**“⽂件缓冲区”**。从内存向磁盘输出数据会先送到内存中的缓冲区,装满缓冲区后才⼀起送到磁盘上。如果从磁盘向计算机读⼊数据,则从磁盘⽂件中读取数据输⼊到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。缓冲区的⼤⼩根据C编译系统决定的。
标签:文件,NULL,int,C语言,pf,FILE,操作,fopen From: https://blog.csdn.net/zxybf_/article/details/137365045