目录
前言
本篇文章将讲解为什么使⽤⽂件、什么是⽂件、⼆进制⽂件和⽂本⽂件、⽂件的打开和关闭、⽂件的顺序读写、⽂件的随机读写、⽂件读取结束的判定、⽂件缓冲区等知识的相关内容,上一篇文章讲解了为什么使⽤⽂件、什么是⽂件、⼆进制⽂件和⽂本⽂件、⽂件的打开和关闭的相关知识,其中⽂件的顺序读写:fgetc、fputc、fgets、fputs、fscanf、fprintf、fread、fwrite函数为本章节知识的内容。
一、⽂件的顺序读写
介绍
文件的顺序读写是指按照数据在文件中的物理存储顺序依次读取或写入,是文件操作中最基础的方式。在C语言中,通过 <stdio.h> 库函数实现,常见函数如下:
| fgetc | 从输⼊流中读取⼀个字符 | 所有输入流 |
| fputc | 从输⼊流中写入⼀个字符 | 所有输出流 |
| fgets | 从输⼊流中读取⼀个字符串 | 所有输入流 |
| fputs | 从输⼊流中写入⼀个字符串 | 所有输出流 |
| fscanf | 从输⼊流中读取带有格式的数据 | 所有输入流 |
| fprintf | 向输出流中写⼊带有格式的数据 | 所有输出流 |
| fread | 从输⼊流中读取⼀块数据 | 文件输入流 |
| fwrite | 向输出流中写⼊⼀块数据 | 文件输出流 |
上⾯说的适⽤于所有输⼊流⼀般指适⽤于标准输⼊流和其他输⼊流(如⽂件输⼊流);所有输出流⼀ 般指适⽤于标准输出流和其他输出流(如⽂件输出流)。
常见函数接下来我将一一介绍:
1.fputc函数
函数形式:
int fputc ( int character, FILE * stream );
介绍:
功能:将参数 character 指定的字符写⼊到 stream 指向的输出流中,通常⽤于向⽂件或标准输 出流写⼊字符。在写⼊字符之后,还会调整指⽰器。字符会被写⼊流内部位置指⽰器当前指向的位置,随后该指示器⾃动向前移动⼀个位置。
参数:
character :被写⼊的字符
stream :是⼀个FILE*类型的指针,指向了输出流(通常是⽂件流或stdout)。返回值:
- 成功时返回写⼊的字符(以int形式)。
- 失败时返回 EOF (通常是-1),错误会被设置,可通过ferror() 检查具体错误。
(ferror()会在下面讲解的)
代码例:
#include
#include
int main()
{
FILE *p=fopen("date.txt","w");
int i=fputc('a',p);
printf("%d",i);
fclose(p);
}

对内容的解释:
打开文件:
FILE *p = fopen("date.txt", "w");
- 以写入模式(
"w")打开文件date.txt。- 若文件不存在,则创建新文件;若已存在,则清空原有内容。
写入字符:
int i = fputc('a', p);
- 调用
fputc向文件流p写入字符'a'。- 成功时,返回写入的字符
'a'(ASCII值为97),并赋值给i。输出返回值:
printf("%d", i);
- 在屏幕上打印
i的值,即字符'a'的ASCII码97。关闭文件:
fclose(p);
- 关闭文件流,释放资源 注意:(必须执行,避免内存泄漏)。
运行结果
- 文件:
date.txt中会写入单个字符a。- 屏幕输出:
97(字符'a'的ASCII值)。
2.fgetc函数
函数形式:
int fgetc ( FILE * stream );
介绍:
功能:从参数 stream 指向的流中读取⼀个字符。函数返回的是⽂件指⽰器当前指向的字符,读取这个字符之后,⽂件指示器将⾃动前进至下⼀个字符。
参数: stream :FILE*类型的⽂件指针,可以是 stdin ,也可以是其他输⼊流的指针。如果是 stdin 就 从标准输⼊流读取数据。如果是⽂件流指针,就从⽂件读取数据。
返回值:
• 成功时返回读取的字符(以 int 形式)。
• 若调⽤时流已处于⽂件末尾,函数返回(feof)
若发⽣读取错误,函数返回 EOF 并设置流的⽂件结束指⽰器( EOF 并设置流的错误指⽰器( ferror )。
(接下来,先说明一下 feof ferror):
feof讲解:
feof 是 C 语言标准库
<stdio.h>中的一个函数,用于检查文件流是否已到达文件末尾。
函数原型:
int feof(FILE *stream);
返回值:
- 非零值:文件流已到达末尾或发生读取错误(需结合
ferror判断具体原因)。- 0:文件流未到达末尾。
结合fgetc示例:
(已经提前准备好 date.txt 文件内容:abcdefg)
#include
#include
int main()
{
FILE* p = fopen("date.txt", "r");
char i;
while ((i=fgetc(p)) !=EOF)
{
printf("%c ", i);
}
if (feof(p))
{
printf("\n无错误\n");
}
fclose(p);
}

ferror讲解:
ferror函数是 C 语言中用于检查文件流是否发生错误的标准库函数,定义在<stdio.h>中。
函数原型:
int ferror(FILE *stream);
功能说明
- 作用:判断指定文件流
stream在上一次的操作中是否发生错误。- 返回值:
- 若发生错误:返回非 0 值(通常为 1)。
- 未发生错误:返回 0。
示例:
(没有提前准备好test.txt文件,找不到该文件的)
#include
#include
int main()
{
FILE* file = fopen("test.txt", "r");
if (file == NULL)
{
perror("fopen failed");
return 1;
}
fclose(file);
}


此时可观察到退出代码不为0,可知,出现了错误。
3.fputs函数
函数形式:
int fputs ( const char * str, FILE * stream );
介绍:
功能:将参数 str 指向的字符串写⼊到参数stream指定的流中(不包含结尾的空字符 \0 ),适⽤于⽂件流或标准输出(stdout)。
参数:
- str :str是指针,指向了要写⼊的字符串(必须以 \0 结尾)。(注意点)
- stream :是⼀个 FILE* 的指针,指向了要写⼊字符串的流。
返回值:
• 成功时返回⾮负整数。
• 失败时返回 EOF (-1),同时会设置流的错误指⽰器,同时可以使⽤ferror() 检查错误原因的。
示例:
#include
#include
int main()
{
FILE* file = fopen("date.txt", "w");
if (file == NULL)
{
perror("fopen failed");
return 1;
}
fputs("666", file);
fclose(file);
}
此时打开文件可看见:

注意:
关键注意事项
不自动添加换行符:
与puts(自动添加'\n')不同,fputs严格写入字符串本身,需手动在str中添加'\n'实现换行。字符串必须以
'\0'结尾:
若str未正确终止,可能导致写入垃圾数据或程序崩溃(未定义行为)。错误处理:
若返回EOF,需通过ferror(stream)确认是否为写入错误。
与 puts 的对比:
| 特性 | fputs(str, stream) | puts(str) |
|---|---|---|
| 输出目标 | 可指定文件流(如文件、stdout) | 固定输出到标准输出(stdout) |
| 换行符 | 不自动添加 '\n' | 自动在字符串后添加 '\n' |
| 返回值 | 成功返回非负值,失败返回 EOF | 成功返回非负值,失败返回 EOF |
4.fgets函数
介绍:
函数形式:
char * fgets ( char * str, int num, FILE * stream );
功能:从 stream 指定输⼊流中读取字符串,⾄读取到换⾏符、⽂件末尾(EOF)或达到指定字符数 (包含结尾的空字符 \0 ),然后将读取到的字符串存储到str指向的空间中。
参数:
• str :是指向字符数组的指针,str指向的空间⽤于存储读取到的字符串。
• num :最⼤读取字符数(包含结尾的 \0 ,实际最多读取 num-1 个字符)。
• stream :输⼊流的⽂件指针(如⽂件流或 stdin )。
返回值:
• 成功时返回 str 指针。
• 若在尝试读取字符时遇到⽂件末尾,则设置⽂件结束指示器,并返回NULL,这需通过 feof()检测出来。
• 若发⽣读取错误,则设置流错误指⽰器,并返回NULL,通过ferror() 即可进行检测。
举例:(已经提前准备好 date.txt 文件内容:666)
#include
#include
int main()
{
FILE* file = fopen("date.txt", "r");
if (file == NULL)
{
perror("fopen failed");
return 1;
}
char a[10];
fgets(a,9,file);
puts(a);
fclose(file);
}

结合例子可知,如果读取的字符数量大于文件中字符串本身的长度的情况下,会将文件中的全部字符读取到字符数组中,并不会报错。
若改文件内容成(abcdefghigklmn),此时:
#include
#include
int main()
{
FILE* file = fopen("date.txt", "r");
if (file == NULL)
{
perror("fopen failed");
return 1;
}
char a[10];
fgets(a,9,file);
puts(a);
fclose(file);
}

获取了8个字符,剩下的那一个给了'\0' ;
使⽤细节:
- 若读取到换⾏符( \n ),会将其包含在字符串中的,以 \0 结尾。
- 如果⽂件末尾⽆换⾏符时,字符串以 \0 结尾,不包含 \n 。
5.fprintf函数
介绍:
函数形式:
int fprintf ( FILE * stream, const char * format, ... );
与printf参数值很像,只是本函数中多了参数:文件指针。
功能: fprintf 是将格式化数据写⼊指定⽂件流的函数。它与 printf 类似,但可以输出到任意 ⽂件(如磁盘⽂件、标准输出、标准错误等),⽽不仅限于控制台。
参数:
- stream :指向 FILE 对象的指针,表⽰要写⼊的⽂件流(stdout 、⽂件指针等)。
- format :格式化字符串,包含要写⼊的⽂本和格式说明符(如 %d 、 %s 等)。
- ... :可变参数列表,提供与格式字符串中说明符对应的数据。
返回值:
• 成功时,返回写⼊的字符总数(⾮负值)。
• 失败时,先设置对应流的错误指⽰器,再返回负值,可以通过 ferror() 来检测。
举例:
#include
#include
int main()
{
FILE* file = fopen("date.txt", "w");
if (file == NULL)
{
perror("fopen failed");
return 1;
}
char a[20] = "abcdefghigklmn";
fprintf(file, "%s", a);
fclose(file);
}
而此时:

可知成功了。
也可以通过返回值知晓是否成功:
fprintf函数的返回值能直接反映其执行状态 ✅。当调用成功时,它会返回实际写入的字符数(不包含字符串结束符
\0);若失败,则返回负数(通常为EOF,即-1)。
#include
#include
int main()
{
FILE* file = fopen("date.txt", "w");
if (file == NULL)
{
perror("fopen failed");
return 1;
}
char a[20] = "abcdefghigklmn";
int i=fprintf(file, "%s", a);
printf("%d",i);
fclose(file);
}

6.fscanf函数
介绍:
函数形式:
int fscanf ( FILE * stream, const char * format, ... );
与scanf函数参数值很像,本函数中多了参数:文件指针。
功能: fscanf 是从指定⽂件流中读取格式化数据的函数。它类似于 scanf ,但可以指定输⼊源 (如⽂件、标准输⼊等),⽽⾮仅限于控制台输⼊。适⽤于从⽂件解析结构化数据(如整数、浮点 数、字符串等)。
参数:
- stream :指向 FILE 对象的指针,表⽰要读取的⽂件流(如 stdin 、⽂件指针等)。
- format :格式化字符串,定义如何解析输⼊数据(如 %d 、 %f 、 %s 等)。
- ... :可变参数列表,提供存储数据的变量地址(需与格式字符串中的说明符匹配)。
返回值:
• 成功时,函数返回成功填充到参数列表中的项数。该值可能与预期项数⼀致,也可能因以下原因少于预期(甚⾄为零):
- 格式和数据匹配失败;
- 读取发⽣错误;
- 到达⽂件末尾(EOF)。
• 如果在成功读取任何数据之前发⽣:
- 发⽣读取错误,会在对应流上设置错误指示符,则返回EOF。
- 到达⽂件末尾,会在对应流上设置⽂件结束指⽰符,则返回EOF。
举例:(已经提前准备好 date.txt 文件内容:abcdefghigklmn)
#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
int main()
{
FILE* file = fopen("date.txt", "r");
if (file == NULL)
{
perror("fopen failed");
return 1;
}
char a[10];
fscanf(file, "%8s", a);
puts(a);
fclose(file);
}

%8s 意思是:取前8个字符,将该字符串存入字符数组a中。
如果读取字符数量超过了数组的上线呢?
#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
int main()
{
FILE* file = fopen("date.txt", "r");
if (file == NULL)
{
perror("fopen failed");
return 1;
}
char a[10];
fscanf(file, "%10s", a);
puts(a);
fclose(file);
}
结果:

由代码值:3 可知,代码有问题。
解析:
问题分析:缓冲区存在溢出风险
fscanf的格式符改为了%10s,但有个细节:char a[10]的实际容量是10字节,其中最后1字节需要存储字符串结束符\0。
%10s会读取最多10个字符,加上自动添加的\0,总长度会达到 11字节,超过了a[10]的容量,依然会导致 缓冲区溢出!- 例如:如果文件中字符串是
"1234567890"(10个字符),fscanf会写入a[0]到a[9],然后在a[10]位置添加\0,但a数组只有a[0]~a[9],越界访问会导致未定义行为(如程序崩溃、数据损坏)。
使用该函数时要注意这些问题。
7. fwrite函数
介绍:
fwrite是 C 语言标准库中用于二进制形式写入数据到文件的函数,位于#include<stdio.h>头文件中。
(fwrite, fread适用于对二进制文件进行操作的情况)
例:⼆进制⽂件"data.bin"
函数形式:
size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );
功能:函数⽤于将数据块写⼊ stream 指向的⽂件流中,是以2进制的形式写⼊的。
参数讲解:
- ptr :指向要写⼊的数据块的指针。
- size :要写⼊的每个数据项的⼤⼩(以字节为单位)。
- count :要写⼊的数据项的数量。
- stream :指向 FILE 类型结构体的指针,指定了要写⼊数据的⽂件流。(即表⽰要写⼊的⽂件流(stdout 、⽂件指针等))
返回值:返回实际写⼊的数据项数量。
如果发⽣错误,则返回值可能⼩于count 。
注意点:
- 需要包含 头⽂件。
- 在使⽤ fwrite() 之前,需要确保⽂件已经以⼆进制可写⽅式打开。
- fwrite() 通常⽤于⼆进制数据的写⼊,如果写⼊⽂本数据,请谨慎处理换⾏符和编码等问题。 (这个注意:fwrite() 通常⽤于⼆进制数据的写⼊)
举例子:
#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
#include
int main()
{
char a[30] = "abcdefghijh";
int i = strlen(a);
FILE* p = fopen("date.bin", "w");
if (p == NULL)
{
printf("打开失败\n");
return;
}
fwrite(a, sizeof(a[0]), i, p);
fclose(p);
}
写入结构体:
#include
#include
typedef struct {
char name[20];
int age;
float score;
} Student;
int main() {
FILE *file = fopen("students.bin", "wb");
if (file == NULL) { perror("Error"); return 1; }
Student stu = {"Alice", 20, 95.5f};
fwrite(&stu, sizeof(Student), 1, file); // 写入整个结构体
fclose(file);
return 0;
}
注意:
fwrite需配合文件打开模式"wb"(二进制写入),若用"w"(文本模式),可能导致换行符\n被自动转换,破坏二进制数据完整性。
8. fread函数
介绍:
函数形式:
size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
功能:函数⽤于从 stream 指向的⽂件流中读取数据块,并将其存储到 ptr 指向的内存缓冲区中。
参数讲解:
• ptr:指向内存区域的指针,⽤于存储从⽂件中读取的数据。
• size:要读取的每个数据块的⼤⼩(以字节为单位)。
• count:要读取的数据块的数量。
• stream:指向FILE类型结构体的指针,指定了要从中读取数据的⽂件流。
返回值:返回实际读取的数据块数量。
记:
- 需要包含#include<stdio.h>头⽂件。
- 在使⽤ fread() 之前,需要确保⽂件已经以⼆进制可读⽅式打开。(记住fwrite于fread均要求⽂件以⼆进制形式打开)
- ptr 指向的内存区域必须⾜够⼤,以便存储指定数量和⼤⼩的数据块。
- 如果 fread() 成功读取了指定数量的数据块,则返回值等于count,如果读取数量少于count,则可能已经到达⽂件结尾或者发⽣了错误。
- 在⼆进制⽂件读取时,fread是我们常⽤的函数,但对于⽂本⽂件读取,通常使⽤fgets()或fscanf即可。
例子:(设该文件中已经有 "Alice", 20, 95.5f 内容了)
#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
#include
typedef struct {
char name[20];
int age;
float score;
} Student;
int main() {
FILE* file = fopen("students.bin", "rb");
if (file == NULL)
{
printf("打开失败\n");
return;
}
Student stu;
fread(&stu, sizeof(Student), 1, file);
printf("%s\n", stu.name);
printf("%d\n", stu.age);
printf("%f\n", stu.score);
fclose(file);
return 0;
}

以此为例。
总结
以上就是今天要讲的内容,本篇文章涉及的C语言⽂件操作讲解的知识点为:⽂件的顺序读写:fgetc、fputc、fgets、fputs、fscanf、fprintf、fread、fwrite函数为本章节知识的内容,希望大家能喜欢我的文章,谢谢各位,接下来新的知识内容我会很快更新。

浙公网安备 33010602011771号