【C语言】文件操作详解2(文件的顺序读写操作)
- 一、引子
- 二、众多函数介绍
-
- [1.单字符输入输出函数(fgetc & fputc)](#1.单字符输入输出函数(fgetc & fputc))
- [2.字符串输入输出函数(fgets & fputs)](#2.字符串输入输出函数(fgets & fputs))
- [3.格式化输入输出函数(fscanf & fprintf)](#3.格式化输入输出函数(fscanf & fprintf))
-
- [(1)fprintf(格式化输出函数)](#(1)fprintf(格式化输出函数))
- (2)fscanf(格式化输入函数)
- [三 、补充一些文件打开方式(二进制文件读写)](#三 、补充一些文件打开方式(二进制文件读写))
-
- 1.二进制文件是什么?
- [2. " rb " (只读)](#2. " rb " (只读))
- [3. " wb " (只写)](#3. " wb " (只写))
- [4. " ab " (追加)](#4. " ab " (追加))
- 四、继续函数介绍(二进制输入输出)
-
- [1.fwrite(二进制输出函数)](#1.fwrite(二进制输出函数))
- [2.fread(二进制输入函数)](#2.fread(二进制输入函数))
- [3. fwrite 和 fread 的返回值](#3. fwrite 和 fread 的返回值)
- 结语
前言:
书接上回,由于文章过长,所以分了三篇文
若内容对大家有所帮助,可以收藏慢慢看,感谢大家支持
谢谢大家 ! ! !
上期给大家介绍了文件的打开与关闭
这期我们就来聊聊文件的顺序读写操作
一、引子
文件开关的标准流程:
- 打开文件(创建文件信息区)
- 读写文件(通过文件指针操作)
- 关闭文件(释放资源)
在打开文件后,就是我们的读写文件了
首先,我们要知道什么是 " 读 " ,什么是 " 写 "****(很重要很重要,易错)
" 读 ":输入数据,将数据从磁盘(文件)中输入到内存中存储
" 写 ":输出数据,将数据从内存中输出到磁盘(文件)中存储
且一定要注意:
先要确定你要进行什么操作(读 & 写)
再选择你的打开方式(" r " & " w ")
(弄混会运行错误)
读写文件时肯定少不了很多函数
小编在这里也是给大家收集了一些常见的函数,希望对大家有用
本期我们就来一 一化解这些函数
二、众多函数介绍
如下图:

大家想要自行了解这些函数的细节也可以到c++官网上去找
小编本人也是经常使用
https://legacy.cplusplus.com/
1.单字符输入输出函数(fgetc & fputc)
讲函数我们先讲输出,再讲输入(下同)
(1)fputc(字符输出函数)
fputc可将内存中的单个字符输出到磁盘(文件)中
fputc语法:
int fputs ( int character, FILE * stream ) ;
character表示要输出的一个字符
stream表示接收字符的文件的文件指针
例如:
fputc('a', pf);输出数据到pf所指向的文件中
fputc的多字符同时输出:
fputc('a', pf);
fputc('b', pf);
fputc('c', pf);
这样就可以做到fputc的多字符同时输出
完整代码演示:
(内有注释,不懂就看)
c
#include<stdio.h>
int main()
{
FILE* pf = fopen("test.txt", "w");
if (pf == NULL)
{
perror("fopen");
//打印出错误信息
return 0;
//返回状态码 1 表示异常退出
}
fputc('a', pf);//输出数据
fputc('b', pf);//同时输出多个数据
fputc('c', pf);
fputc('d', pf);
fputc('e', pf);
fputc('f', pf);
fputc('g', pf);
fclose(pf);//关闭文件
pf = NULL;//置为NULL空指针
return 0;
}
运行结果:
文件被输入了字符 " abcdefg "

但是,在多组同时输出时,有一个小小的疑问
为什么每个字符都是连续排列的?
难道每次写入字符后文件光标会自动后移吗?
事实也确实如此,在每次写入字符后文件光标会自动后移所以每个字符都是连续的
(2)fgetc(字符输入函数)
fgetc可将磁盘(文件)的单个字符输出到内存的变量中
fgetc语法:
int fgetc ( FILE * stream );
stream表示接收字符的文件的文件指针
代码演示:
现在,我们先将文件中存放 " abcdefg "
再用
fgetc读取文件的数据
注意:
因为fgetc函数一次性只能读取一个字符
所以我们可以加入一个循环来读取多个字符
(内有注释,不懂就看)
c
#include<stdio.h>
int main()
{
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
//打印出错误信息
return 0;
//返回状态码 1 表示异常退出
}
for(int i=1;i<=7;i++)
{
printf("%c ", fgetc(pf));
//加入一个循环来读取多个字符并打印
}
printf("\n\n");
fclose(pf);//关闭文件
pf = NULL;//置为NULL空指针
return 0;
}
运行结果:(事先在文件中存储了数据)

以上的代码通过了一个循环来达到读取并打印多个字符的结果
当然还有一种改进代码也可以实现
这里就要用到fgetc的返回值
fgetc的返回值:
int fgetc ( FILE * stream );
正常读取时:返回读到字符的ASCLL码值
读取失败时:返回EOF在文件操作中,EOF 是 "End of File"(文件结束)的缩写,用于指示文件的结束
代码演示:(利用fgetc的返回值)
(内有注释,不懂就看)
c
#include<stdio.h>
int main()
{
char ch;
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
//打印出错误信息
return 0;
//返回状态码 1 表示异常退出
}
while ((ch = fgetc(pf)) != EOF)
//当返回值不为EOF时,继续
//可以把所有字符打印出来
{
printf("%c ", ch);
}
printf("\n\n");
fclose(pf);//关闭文件
pf = NULL;//置为NULL空指针
return 0;
}
运行结果:

当然,代码结果是一样的,但代码要更加高效精简
2.字符串输入输出函数(fgets & fputs)
(1)fputs(字符串输出函数)
fputs可将内存中的字符串输出到磁盘(文件)中
fputs语法:
int fputs ( const char * str, FILE * stream );
str表示要输出的字符串
stream表示接收字符串的文件的文件指针
例如:
fputs("abcdefg\n", pf);(可加换行符 \n )
输出数据到pf所指向的文件中
代码演示:
注意,fputs 不会自动换行,要手动换行
(内有注释,不懂就看)
c
#include<stdio.h>
int main()
{
char ch;
FILE* pf = fopen("test.txt", "w");
if (pf == NULL)
{
perror("fopen");
//打印出错误信息
return 0;
//返回状态码 1 表示异常退出
}
fputs("Hi\n", pf);//手动换行
fputs("I am a student", pf);
printf("\n\n");
fclose(pf);//关闭文件
pf = NULL;//置为NULL空指针
return 0;
}
运行结果:

可以看到,输出时手动换行成功
(2)fgets(字符串输入函数)
fgets可将内存中的字符串输入到磁盘(文件)中
fgets语法:
char * fgets ( char * str, int num, FILE * stream );
str指向字符数组的指针,用于存储读取的字符串
num表示最大读取字符个数
stream表示接收字符串的文件的文件指针
例如:
fgets(str, 20, pf);
将数据输入到str中
但使用fgets有两个要注意的点:
一、
fgets读取字符时不会真的读取num个字符,在读取到的字符串的末尾还会存储一个" \0 "
代码演示:
先在新建文件中写20个字符,这里我写的是
(11112222333344445555)方便观察
再读取到str中,最后打印出来
(内有注释,不懂就看)
c
#include<stdio.h>
int main()
{
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
//打印出错误信息
return 0;
//返回状态码 1 表示异常退出
}
char str[20];
fgets(str, 20, pf);
printf("%s", str);//打印读取的字符串
printf("\n\n");
fclose(pf);//关闭文件
pf = NULL;//置为NULL空指针
return 0;
}
运行结果:

可以看到,本应该的打印20个字符却少了一个变成了19个
这就是因为在读取到的字符串末尾还会存储一个 " \0 "
故实际只存储 num-1 个字符
二、
fgets读取时遇到换行符时停止读取不管下一行还有多少字符
代码演示:
先在新建文件中写两行字符
这里我写的两行分别是(Hello)和(world)方便观察

再读取到str中,最后打印出来
代码:
(内有注释,不懂就看)
c
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
//打印出错误信息
return 0;
//返回状态码 1 表示异常退出
}
char str[20];
fgets(str, 20, pf);
printf("%s", str);//打印读取的字符串
printf("\n\n");
fclose(pf);//关闭文件
pf = NULL;//置为NULL空指针
return 0;
}
运行结果:

可以看到,str 接收数据时只接收了第一行的" Hello ",而第二行不会读取
所以可得,fgets读取时遇到换行符时停止读取不管下一行还有多少字符
3.格式化输入输出函数(fscanf & fprintf)
(1)fprintf(格式化输出函数)
fprintf可将任意类型的数据从内存中输出到磁盘(文件)中
fprintf语法:
int fprintf ( FILE * stream, const char * format, ... );
stream表示文件的文件指针
format是输出的形式(%d,%f,%s······)
最后的...是可变参数列表,可一个或多个变量
代码演示:
演示如何用fprintf将数据输出到文件中
(内有注释,不懂就看)
c
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
FILE* pf = fopen("test.txt", "w");
if (pf == NULL)
{
perror("fopen");
//打印出错误信息
return 0;
//返回状态码 1 表示异常退出
}
char name[20]="xiaobai";
int age=18;
float score=8.29;
//定义变量名将要输出的数据写入
fprintf(pf, "%s %d %.2f", name, age, score);
//输出数据,将数据输出到磁盘(文件)中
printf("\n\n");
fclose(pf);//关闭文件
pf = NULL;//置为NULL空指针
return 0;
}
运行结果:

可见,我们将变量中的数据输出到了文件中,且分别输出了字符串、整型、浮点型
说明fprintf函数可以格式化输出数据(输出任何类型数据)到磁盘(文件)中
(2)fscanf(格式化输入函数)
fscanf可将任意类型的数据从磁盘(文件)中输入到内存中
fscanf语法:
int fscanf ( FILE * stream, const char * format, ... );
stream表示文件的文件指针
format是输出的形式(%d,%f,%s······)**
最后的...是可变参数列表的地址,可一个或多个变量的地址
代码演示:
现在,我们来演示如何用fscanf函数将数据从文件中输入到内存中的变量中
首先,我们创建一个文件,写入一些数据
(这里我写的是xiaobai 18 8.29)
(写了三个数据,分别是字符串,整型,浮点型)
如下:

然后运行代码将数据输入到早已定义好的变量中:
(内有注释,不懂就看)
c
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
//打印出错误信息
return 0;
//返回状态码 1 表示异常退出
}
char name[20];
int age;
float score;
//定义三个变量名用于接收数据
fscanf(pf, "%s %d %f", &name, &age, &score);
//通过变量的地址将数据储存
//读取数据,将数据存在变量中
printf("%s %d %.2f", name, age, score);
//将变量一一打印验证效果
printf("\n\n");
fclose(pf);//关闭文件
pf = NULL;//置为NULL空指针
return 0;
}
运算结果:

可见,我们将文件中的数据输出到了内存的变量中
且分别输入了字符串、整型、浮点型,最后打印出
说明fscanf函数可以格式化输入数据(输入任何类型数据)从文件中输入到内存的变量
三 、补充一些文件打开方式(二进制文件读写)
之前,我给大家讲解了
" r " , " w , " a "三种文件打开方式
现在,给大家补充一些涉及到二进制文件的读写

1.二进制文件是什么?
上一期我们讲解了文本文件与二进制文件的区别
本篇也不赘述,大家可自行查看
【C语言】文件操作详解1(文件的打开与关闭)
2. " rb " (只读)
为了输入数据,打开一个二进制文件 ( 若文件不存在,就报错 )
例如:FILE* pf = fopen("test.txt", "rb");
3. " wb " (只写)
为了输出数据,打开一个二进制文件 ( 若文件不存在,就新建一个文件 )
例如:FILE* pf = fopen("test.txt", "wb");
4. " ab " (追加)
为了在一个二进制文件末尾添加数据 ( 若文件不存在,就新建一个文件 )
例如:FILE* pf = fopen("test.txt", "ab");
当然,这里先简单介绍,待会再用代码进行演示
四、继续函数介绍(二进制输入输出)
1.fwrite(二进制输出函数)
将内存中的数据以二进制形式输出到文件中
fwrite语法:
size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );
ptr为指向要输出的元素数组的指针
size表示每个要输出元素的字节大小
count表示要输出多少个元素
stream表示接收数据的文件的文件指针
代码演示:
(内有注释,不懂就看)
现在,我们定义一个结构体类型,再将结构体中的数据输出到文件中
c
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
struct Stu
{
char name[20];
int age;
float score;
}S1;//定义结构体
int main()
{
struct Stu S1 = { "xiaobai",18,8.29 };
//初始化结构体
FILE* pf = fopen("test.txt", "wb");
//打开文件
if (pf == NULL)
{
perror("fopen");
//打印出错误信息
return 0;
//返回状态码 1 表示异常退出
}
fwrite(&S1, sizeof(struct Stu), 1, pf);//将结构体中的数据输出到文件中
//第一个参数是结构体的地址
//第二个参数是该结构体的大小
//第三个参数是要输出几个元素
//第四个参数是文件指针
printf("\n\n");
fclose(pf);//关闭文件
pf = NULL;//置为NULL空指针
return 0;
}
运行结果:

可以看到,文件中出现了很多乱码
其实这就是二进制序列,只是转换成文本文件我们看不懂
我们依靠fwrite函数,可将内存中的数据以二进制形式输出到文件中
2.fread(二进制输入函数)
将文件中的二进制数据输出到内存中
fread语法:
size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
ptr为指向要输入的元素数组的指针
size表示每个要输入元素的字节大小
count表示要输入多少个元素
stream表示文件的文件指针
可翻译为:
从stream所指向的文件中读取count个大小为size个字节的数据,并存放在ptr指向的空间中
代码演示:
现在我运行代码读取之前fwrite输出形成的二进制文件
最后打印看看结果如何,是不是之前结构体的数据
(内有注释,不懂就看)
c
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
struct Stu
{
char name[20];
int age;
float score;
}S;//定义结构体
int main()
{
FILE* pf = fopen("test.txt", "rb");
//打开文件
if (pf == NULL)
{
perror("fopen");
//打印出错误信息
return 0;
//返回状态码 1 表示异常退出
}
fread(&S, sizeof(struct Stu), 1, pf);//将文件中的数据输入到结构体中
//第一个参数是结构体的地址
//第二个参数是该结构体的大小
//第三个参数是要输入几个元素
//第四个参数是文件指针
printf("%s %d %.2f", S.name, S.age, S.score);
//将读取到的数据打印出来验证结果
printf("\n\n");
fclose(pf);//关闭文件
pf = NULL;//置为NULL空指针
return 0;
}
运行结果:

结果显示,读取数据成功,是之前的数据
所以,fread可将文件中的二进制数据输出到结构体中
3. fwrite 和 fread 的返回值
fwrite 和 fread 的返回值是实际输入或输出的总个数
结语
本期资料来自于:

OK,本期的文件操作详解到这里就结束了
由于文章过长,所以分了三篇文
下期我们讲解文件的随机读写操作和其他补充
若内容对大家有所帮助,可以收藏慢慢看,感谢大家支持
本文有若有不足之处,希望各位兄弟们能给出宝贵的意见。谢谢大家!!!
新人,本期制作不易希望各位兄弟们能动动小手,三连走一走!!!
支持一下(三连必回QwQ)