一、fopen文件的打开操作
函数原型
#include <stdio.h>
FILE *fopen( const char *fname, const char *mode );
参数1: fname 表示文件名(可以含有路径信息)
参数2: 打开方式
返回值: FILE* 文件指针(非0),
如果打开失败,就返回NULL(就是0)
mode 打开方式
" r " 以“读”的方式打开一个文本文件(只能读)
" r+ " 与"r" 的区别在于,增加了“写”
" rb " 以“读”的方式打开一个二进制文件(只能读)
" rb+ " 与"rb"的区别在于,增加了“写”
" w " 以“写”的方式创建一个文本文件,如果这个文件已经存在,就会覆盖原来的文件
" w+ " 与"w"的区别在于,增加了“读”
" wb " 以“写“的方式创建一个二进制文件
" wb+ " 与"wb"的区别在于,增加了“读”
" a " 以“尾部追加”的方式打开一个文本文件, (只能写)上面的那些打开方式指针都是在首部
" a+ " 以"a"的区别在于,增加了"读"
" ab " 以“尾部追加”的方式打开一个二进制文件, (只能写)
" ab+ " 与"ab"的区别在于,增加了“读”
代码实例
#include <stdio.h>
#include <string.h>
int main(void){
FILE *file; //定义文件指针
file = fopen("D:\\note\\students.txt","r"); //打开后内存需要存储打开的文件,所以需要一个文件指针知道内存的地址, 路径要用双斜杠\\,
if(!file){ //不过文件一般都放在程序目录下,直接是文件名:("students.txt","r")
printf("文件打开失败!");
}else{
printf("文件打开成功!");
}
return 0;
}
注意:FILE *file; 和 file = fopen( ); 一起出现。
作用就是定义文件指针,因为文件打开后内存需要存储打开的文件,所以需要一个文件指针知道内存的地址,以便找到文件内容。
二、fclose文件的关闭操作
清理缓冲区,并释放文件指针。
#include <stdio.h>
#include <string.h>
int main(void){
FILE *file;
file = fopen("students.txt", "a");
fputs("\neet 123456", file); // '\n' 表示换行,从新的一行开始
fclose(file); //执行这个关闭操作后,写的内容才真正写入到students.txt文件里面
return 0 ;
}
特别注意:
如果对文件只是" r "读操作,不用fclose清理缓冲区也没关系。
但对文件执行写操作以后,并不会马上写入文件,而只是写入到了这个文件的输出缓冲区中(文件打开后的内存缓存区)!
只有当:
1、这个输出缓冲区满了,
2、或者执行了fflush,
3、或者执行了fclose函数以后,
4、或者程序结束,
才会把输出缓冲区中的内容正真写入文件!
三、fgetc文件的读取操作
函数原型:
#include <stdio.h>
int fgetc( FILE *stream );
返回值: 成功时,返回读到的字符,返回的是int类型(实际值是字符)
失败或读到文件尾,返回EOF (就是-1)
作用:从文件中读取一个字符。 getchar(); 是从键盘输入中读取一个字符。
#include <stdio.h>
#include <string.h>
int main(void){
FILE *file;
char c; //定义字符型变量c
file = fopen("students.txt", "r"); //打开文件
while(1){
c = fgetc(file);
if(c == EOF){ //EOF就是 -1 ,读取不到字符就停止打印
break;
}
printf("%c",c);
}
fclose(file);
return 0;
}
/*
循环体也可以写成这样:
while((c = fgetc(file)) != EOF) {
printf("%c", c);
}
*/
这个代码就是通过循环,把文件 students.txt 的全部内容打印出来。
四、fputc写一个字符到文件
函数原型:
#include <stdio.h>
int fputc( int ch, FILE *stream ); 成功时返回值是写成功的字符(非0),失败返回值为EOF。
#include <stdio.h>
int main(void){
FILE *file1;
FILE *file2;
char c;
file1 = fopen("students.txt", "r"); //打开文件
file2 = fopen("students1.txt", "w");
while(1){
c = fgetc(file1); //从本文件读一个字符
if(c == EOF){ //EOF就是 -1 ,读取不到字符就停止复制
break;
}
fputc(c,file2); //把这个字符写入另一个文件
}
fclose(file1);
fclose(file2);
return 0;
}
代码实现的是复制 file1 文件,变成 file2 文件。
五、fgets 从文件中读取一行字符串
fgetc 和 fputc 都是对单个字符进行操作,处理的字符串长度大的话,需要循环的次数多,所以效率不高。
fgets 可以每次读取一定长度的字符串,效率提高了很多。参考之前的文章:C语言关于字符串的输入
函数原型:
#include <stdio.h>
char * fgets( char *str, int num, FILE *stream );
参数:
num:一行最多读取num-1个字符,或者遇到换行符或者文件结束符EOF(即“文件读完了”)停止读取
返回值: 读取失败时,返回 NULL
读取成功时,返回 str
#include <stdio.h>
int main(void){
FILE *file;
char line[128];
char *ret; //定义返回值变量,指针类型
file = fopen("students.txt", "r"); //打开文件
if(!file){ //判断文件打开是否失败
printf("文件打开失败!");
return 1;
}
while(1){
ret = fgets(line,sizeof(line),file); //返回值是指针变量
if(ret == NULL){
break;
}
printf("%s",line);
}
fclose(file);
return 0;
}
/*
循环代码等效:
while(fgets(line,sizeof(line),file) != NULL){
printf("%s",line);
}
*/
代码就是读取 file 文件的内容,并打印出来。注意的地方是:文件读完返回值是 NULL
六、fputs 写一个字符串到文件中去
函数原型:
#include <stdio.h>
int fputs( const char *str, FILE *stream );参数一:要写的字符串,参数二:文件指针
最简单的用法:
#include <stdio.h>
int main(void){
fputs("hello,world!",stdout); //等同于printf("hello,world!"); stdout 是标准输出
return 0;
}
当然 fputs 的强大是因为 第二个参数stdout 可以换成文本格式,然后把第一个参数获取的内容写到文本中去!
#include <stdio.h>
int main(void){
FILE *file1;
FILE *file2;
char line[128]; //读取出来的是字符串
file1 = fopen("students.txt","r"); //先打开文件
file2 = fopen("students1.txt","w");
if(!file1 || !file1){
printf("打开文件失败!");
return 1;
}
while(fgets(line,sizeof(line),file1) != NULL){ //读取到 line
fputs(line,file2); //从 line 写入到 file2指针指向的地址
}
fclose(file1);
fclose(file2);
return 0;
}
//判断 语句直接写成 while(fgets(line,sizeof(line),file1)) 也行,因为正常情况下返回值都不是NULL,非0都是真
代码实现的是把 file1 文件内容拷贝到 新文件file2 中! 可以跟上文三、四的 fgetc 和 fputc 与 fgets 和 fputs 对比看看不同点。
七、fprintf 往文件中写格式化数据
函数原型:
#include <stdio.h>
int fprintf( FILE *stream, const char *format, ... ); printf 是把格式字符串打印到输出屏中,fprintf 则是把格式字符串打印到文本中。
#include <stdio.h>
/*
*需求:让用户输入学员的姓名、年龄,
并把这些信息按照如下格式,保存到文件students.txt
姓名:张三 年龄:13
姓名:李四 年龄:15
*/
int main(void){
//1.1.1定义变量
char name[32];
int age;
//1.2.1定义文件指针
FILE *file;
//2.1定义判断条件
char c;
//1.2.2打开文件,判断文件是否打开成功
file = fopen("students.txt","w"); //如果是追加写入,打开方式用"a"
if(!file){
printf("打开文件失败!\n");
return 1;
}
//1、先建立循环框架------------------------------------------
while(1){
//1.1提示用户输入
printf("请输入学员姓名:");
scanf("%s",name);
printf("请输入学员年龄:");
scanf("%d",&age);
//1.2按指定格式,保存到文件
fprintf(file,"姓名:%s\t年龄:%d\n",name,age);
//--------------------------------------------------------
//2、提示是否继续输入----------------------------------------
printf("是否继续输入?Y/N\n");
fflush(stdin); //2.2清空输入缓冲区,防止1.1处输入时有缓存被下面的scanf直接读取
scanf("%c",&c);
if(c == 'Y' || c == 'y'){
continue;
}else{
break;
}
//--------------------------------------------------------
}
fclose(file);
return 0;
}
八、fscanf 格式化读取文件中数据
函数原型:
#include <stdio.h>
int fscanf( FILE *stream, const char *format, ... );
返回值:成功时,返回实际读取的数据个数
失败时,返回 EOF (-1)
作用:scanf 是从键盘中读取输入,写入变量中,fscanf 可以从文本中读取数据写入变量中。
有这么一个文本 info.txt ,里面按一定格式存了姓名和年龄,要求读取里面的姓名和年龄。
#include <stdio.h>
int main(void){
FILE *file;
char name[32];
int age;
int ret; //返回值
file = fopen("info.txt","r"); //打开文件
if(!file){
printf("打开文件失败!");
return 1;
}
while(1){
ret = fscanf(file,"姓名:%s 年龄:%d\n",name,&age);
if(ret == EOF){
break;
}
printf("%s,%d\n",name,age);
}
return 0;
}
/*
循环等效:
while(fscanf(file,"姓名:%s 年龄:%d\n",name,&age) != EOF){
printf("%s,%d\n",name,age);
}
*/
区分 scanf 、 sscanf 、 fscanf
scanf 是从 stdin 标准输入中读取信息写入变量。sscanf 是从缓冲区中读取信息写入变量(使用时要程序读取一行字符串先写入变量中,然后 sscanf 从变量中读取)。fscanf 是从文本中读取信息写入变量。
九、fwrite 以二进制形式写数据到文件中去
函数原型:
#include <stdio.h>
int fwrite( const void *buffer, //要写入的数据的其实地址,也就是变量的地址
size_t size, //每“块”数据的大小
size_t count, //写入几块数据
FILE *stream );
FILE *file;
int age;
file = fopen("info.txt","wb");
printf("输入年龄:");
scanf("%d",&age);
fwrite(&age,sizeof(int),1,file); //取址符不要忘记 &age
十、fread 以二进制形式读取文件中的数据
函数原型:
#include <stdio.h>
int fread( void *buffer, size_t size, size_t num, FILE *stream );
对应 fwrite 存在;以 fwrite 写数据,就必须用 fread 读取。参数跟 fwrite 一样,下面代码就是把第九点的内容读取出来:
FILE *file;
int age;
file = fopen("info.txt","rb");
fread(&age,sizeof(int),1,file);
十一、putw 以二进制形式存贮一个整数
把一个int数组,写到文件 test.data :
#include <stdio.h>
int main(void){
FILE *file;
int data[5] = {0,1,2,3,4};
int i;
file = fopen("test.data","wb"); // "wb" 创建一个二进制文件
if(!file){
printf("打开文件失败!");
return 1;
}
for(i = 0;i < 5;i++){
putw(data[i],file);
}
fclose(file);
return 0;
}
十二、getw 以二进制形式读取一个整数
对应 putw 存在。函数原型:
int getw(FILE *fp);
返回值:成功时返回读取到的值
失败时返回-1。
下面代码就是把第十一点的内容读取出来:
#include <stdio.h>
int main(void){
FILE *file;
int d;
file = fopen("test.data","rb"); // "rb" 以“读”的方式打开一个二进制文件
if(!file){
printf("打开文件失败!");
return 1;
}
while((d = getw(file)) != -1){ //为避免整数里面含有 -1
printf("%d\n",d);
}
fclose(file);
return 0;
}
/*
//为避免整数里面含有 -1 循环代码写成:
while(1){ //
d = getw(file);
if(d == -1 && feof(flie)){ // feof(flie)判断一个文件是否结束
break;
}
printf("%d\n",d);
}
*/