文章目录
为什么使用文件?
如果没有文件,我们写的程序的数据是存储在电脑内存中的,如果程序退出,内存回收,数据就丢失了,等再次运行程序,是看不到上次程序的数据的,如果想要将程序中的数据长期保存,我们可以使用文件。
文件类型
在程序设计中,我们一般谈的文件有两种:程序文件、数据文件(从文件功能的角度来分类的)。
程序文件
程序文件包括源程序文件(.c),目标文件(windows环境下后缀是.obj),可执行文件(windows环境下后缀是.exe)。
数据文件
文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件,或者输出内容的文件。
二进制文件
数据文件也分为二进制文件或者文本文件。
数据在内存中以二进制的形式存储,如果不加转换的输出到外存的文件中,就是二进制文件。
如果要求数据在外存中以ASCLL的形式存储,则需要在存储前加以转换以ASCLL字符形式存储的文件就是文本文件。
字符一律以ASCLL形式存储,数值型数据可以用ASCLL形式也可以用二进制形式存储
文件的打开与关闭
文件在读写之前应该先打开文件,在使用结束之后应该关闭文件。
在编写程序的时候,在打开文件的同时,都会返回一个FILE*的指针变量指向该文件,也相当于建立了指针和文件的关系。
ANSI C 规定使用 fopen函数来打开文件,fclose 来关闭文件。
//打开文件
FILE* fopen(const char * filename,const char* mode)
if(fp==NULL){
perror("fopen");
return 1;
}
//关闭文件
fclose(FILE* stream)
//释放的内存置为空
fp=NULL
流与标准流
流
我们程序的数据需要输出到各种外部设备,也需要从外部设备获取数据,不同的外部设备的输入输出操作各不相同,为了方便程序员对各种设备进行方便的操作,我们抽象出了流的概念,我们可以把流想象成流淌着字符的河。C程序针对文件、画面、键盘等的数据输入输出操作都是通过流操作的。
一般情况下,我们要想向流里写数据,或者从流中读取数据,都是要打开流,然后操作。
标准流
那为什么我们从键盘输入数据,向屏幕上输出数据,并没有打开流呢?
那是因为C语言程序在启动的时候,默认打开了3个流:
· stdin-标准输入流,在大多数的环境中从键盘输入,scanf函数就是从标准输入流中读取数据。
· stdout-标准输出流,大多数的环境中输出至显示器界面,printf函数就是将信息输出到标准输出流中。
· stderr-标准错误流,大多数环境中输出到显示器界面。
这是默认打开了这三个流,我们使用scanf、printf等函数就可以直接进行输入输出操作的。
stdin、stdout、stderr 三个流的类型是:FILE *,通常称为文件指针。
C语言中,就是通过FILE*的文件指针来维护流的各种操作的。
文件指针
缓冲文件系统中,关键的概念是”文件类型指针“,简称”文件指针“。
每个被使用的文件都在内存中开辟了一个相应的内存信息区,存放的是文件的相关信息,这些信息保存在一个结构体变量中,该结构体类型由系统声明,取名为FILE。
文件的顺序读写
以上代码在本篇文章中只做简单讲解,具体可在cplusplus中查看。
fgetc
该函数可从文件中读取一个字符。
下面是函数声明:
int fgetc(FILE* stream)
- stream – 这是指向 FILE 对象的指针,该 FILE对象标识了要被写入字符的流。
FILE* fp=fopen("test.txt","r");//以只读形式打开文件
if(fp==NULL){
perror("fopen");
return 1;
}
char c=fgetc(fp);//用c接受在test.txt读取的字符
fclose(fp);//关闭文件
fp=NULL;//释放的内存置为空
fputc
该函数可往文件中写入一个字符。
下面是函数声明:
int fputc(int char, FILE* stream)
- char-是要写入的字符。
- stream-这是指向 FILE 对象的指针,该 FILE 对象标识了要从中读取字符的流。
FILE* fp=fopen("test.txt","w")//以只写形式打开文件
if(fp==NULL){
perror("fopen");
return 1;
}
char ch=c;
fputc(ch,fp);//往test.txt写入字符ch
fclose(fp)//关闭文件
fp=NULL//释放的内存置为空
fgets
该函数从指定的流中读取一行,并存储到str所指向的字符串中,当读取到(n-1)或者读取到换行符时停止。
下面是函数声明:
int fgets(char* str,int num,FILE* stream)
- str-这是一个指向字符数组的指针,该数组存储了读取的字符串。
- num-要读取的最大字符数。
- stream-这是指向 FILE 对象的指针,该 FILE 对象标识了要从中读取字符的流。
FILE* fp=fopen("test.txt","r");//以只读方式读取文件
if(fp==NULL){
perror("fopen");
return 1;
}
char str[60];
fgets(str,10,fp);//读取10个字符
fclose(fp);
fp=NULL;
fputs
该函数可往指定的流写入一行,对于大小为size的buf,最多只读取size-1个字符。遇到换行符结束。自动地把buf中最后一个字符(通常是换行符)的后面一个字节填充零结束符(‘/0’)。
下面是函数声明:
int fputs(const char *s, FILE *stream)
- str-这是一个字符数组,包含了要写入的以空字符终止的字符序列
- stream-这是指向FILE对象的指针,该FILE对象标识了要被写入字符串的流。
FILE* fp=fopen("test.txt","w");
if(fp==NULL){
perror("fopen");
return 1;
}
fputs("abcde",fp);
fclose(fp);
fp=NULL;
fscanf
该函数可以从流读取格式化输入
下面是函数声明:
int fscanf(FILE *stream, const char *format, ...)
- stream-这是指向FILE对象的指针,该FILE对象标识了要被写入字符串的流。
- format – 这是 C 字符串,包含了以下各项中的一个或多个:空格字符、非空格字符 和 format 说明符。
FILE* fp=fopen("test.txt","w+");//以读写形式打开文件
if(fp==NULL){
perror("fopen");
return 1;
}
char str[10];
int n;
fputs("abcd 10",fp);//写入字符串
fscanf(fp,"%s %d",str,n);//格式化读取
fclose(fp);
fp=NULL;
fprintf
该函数可发送格式化输出到流
下面是函数声明:
int fprintf(FILE *stream, const char *format, ...)
- 参数与fscanf函数一致。
FILE* fp=fopen("test.txt","w");
if(fp==NULL){
perror("fopen");
return 1;
}
fprint(fp,"%c %s %d",c,abcde,10);//格式化输出
fclose(fp);
fp=NULL;
fwrite
该函数 size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) 把 ptr 所指向的数组中的数据写入到指定流 stream 中。
下面是函数声明:
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
- ptr – 这是指向要被写入的元素数组的指针。
- size – 这是要被写入的每个元素的大小,以字节为单位。
- nmemb – 这是元素的个数,每个元素的大小为 size 字节。
- stream – 这是指向 FILE 对象的指针,该 FILE 对象指定了一个输入流。
FILE* fp=fopen("test.txt","wb");
if(fp==NULL){
perror("fopen");
return 1;
}
char str[]="abcde";
fwrite(str,sizeof(str),1,fp);以二进制形式写入
fclose(fp);
fp=NULL;
fread
该函数 size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) 从指定流读取数据到ptr所指向的数组中
下面是函数声明:
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
- ptr – 这是指向带有最小尺寸 size*nmemb 字节的内存块的指针。
- size – 这是要读取的每个元素的大小,以字节为单位。
- nmemb – 这是元素的个数,每个元素的大小为 size 字节。
- stream – 这是指向 FILE 对象的指针,该 FILE 对象指定了一个输入流。
FILE* fp=fopen("test.txt","w+");
if(fp==NULL){
perror("fopen");
return 1;
}
char str[]="abcde";
char buf[20];
fwrite(str,strlen(str)+1,1,fp);//以二进制形式写入
fread(buf,strlen(str)+1,1,fp);//以二进制形式读取
fclose(fp);
fp=NULL;