news 2026/4/16 11:50:44

【C 语言进阶】一文吃透文件读写:从基础到实战,附完整代码示例 [特殊字符]

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【C 语言进阶】一文吃透文件读写:从基础到实战,附完整代码示例 [特殊字符]

在 C 语言开发中,文件读写是不可或缺的核心技能 —— 无论是处理配置文件、存储用户数据,还是实现日志功能,都离不开对文件的操作。今天这篇笔记,会从文件操作的基本概念入手,逐步拆解打开、关闭、读写文件的关键函数,并结合实战代码演示,帮你彻底掌握 C 语言文件读写的精髓!

一、文件读写前必知:文件指针与打开模式 📌

在 C 语言中,所有文件操作都围绕文件指针(FILE *展开,它就像 “文件的身份证”,记录着文件的位置、状态等关键信息。使用前需先通过fopen()函数打开文件并获取指针,而打开模式决定了文件的操作权限,常见模式如下:

打开模式

含义

适用场景

r

只读打开(文件必须存在)

读取配置文件、日志文件

w

只写打开(文件不存在则创建,存在则清空)

新建 / 覆盖写入文件(如输出结果)

a

追加写入(文件不存在则创建,存在则在末尾追加)

记录日志、累加数据

r+

读写打开(文件必须存在,可修改内容)

编辑已有文件

w+

读写打开(文件不存在则创建,存在则清空)

新建可读写文件

a+

读写打开(文件不存在则创建,写操作只能追加)

边读边追加数据

二、核心函数拆解:打开→读写→关闭 🔧

文件操作的流程遵循 “打开→操作→关闭” 的逻辑,任何环节出错都可能导致文件损坏或数据丢失,下面逐个讲解关键函数。

1. 打开文件:fopen()

  • 函数原型:FILE *fopen(const char *filename, const char *mode);
  • 作用:按指定模式打开文件,返回文件指针;若失败(如路径错误、权限不足),返回NULL。
  • 注意:打开文件后必须判断指针是否为NULL,避免后续操作崩溃!

示例代码(打开一个文本文件):

#include <stdio.h>

int main() {

// 以只读模式打开当前目录下的 "test.txt"

FILE *fp = fopen("test.txt", "r");

// 判断文件是否成功打开

if (fp == NULL) {

printf("文件打开失败!❌\n");

return 1; // 失败退出

}

printf("文件打开成功!✅\n");

// 后续操作...

// 关闭文件(关键!避免内存泄漏)

fclose(fp);

return 0;

}

2. 关闭文件:fclose()

  • 函数原型:int fclose(FILE *stream);
  • 作用:关闭已打开的文件,释放文件指针占用的资源;成功返回0,失败返回EOF(-1)。
  • 注意:文件使用完后必须关闭!若程序异常退出未关闭,可能导致数据未写入磁盘或文件损坏。

3. 文本文件读写:常用函数对比

文本文件读写主要有两类函数:按字符读写(适合逐字符处理)和按行读写(适合批量处理),具体用法如下:

(1)按字符读写:fgetc() & fputc()
  • fgetc(fp):从文件指针fp指向的文件中读取一个字符,返回该字符的 ASCII 值;若读到文件末尾,返回EOF。
  • fputc(ch, fp):将字符ch写入文件指针fp指向的文件,成功返回该字符,失败返回EOF。

示例(复制一个文本文件):

#include int main() {

// 打开源文件(只读)和目标文件(只写,不存在则创建)

FILE *src = fopen("source.txt", "r");

FILE *dest = fopen("destination.txt", "w");

if (src == NULL || dest == NULL) {

printf("文件打开失败!❌\n");

return 1;

}

int ch; // 注意:用int接收fgetc(),避免EOF(-1)与char的255冲突

// 逐字符读取源文件,直到末尾

while ((ch = fgetc(src)) != EOF) {

fputc(ch, dest); // 逐字符写入目标文件

}

printf("文件复制完成!✅\n");

// 关闭文件

fclose(src);

fclose(dest);

return 0;

}

(2)按行读写:fgets() & fputs()
  • fgets(buf, n, fp):从文件中读取一行字符,存入缓冲区buf,最多读取n-1个字符(最后留\0);若读到换行符或文件末尾,停止读取,返回buf地址;失败返回NULL。
  • fputs(buf, fp):将缓冲区buf中的字符串(不含\0)写入文件,成功返回非负值,失败返回EOF。

示例(读取文件内容并打印,同时追加一行数据):

#include >

#include >

int main() {

char buf[1024]; // 定义缓冲区,存储一行数据

FILE *fp = fopen("test.txt", "a+"); // 读写模式,可追加

if (fp == NULL) {

printf("文件打开失败!❌\n");

return 1;

}

// 先读取文件原有内容(需将文件指针移到开头,a+模式默认在末尾)

rewind(fp); // 移动指针到文件开头

printf("文件原有内容:\n");

while (fgets(buf, sizeof(buf), fp) != NULL) {

printf("%s", buf); // 打印每行内容(fgets会读取换行符)

}

// 追加一行数据

char new_data[] = "This is new content!\n";

fputs(new_data, fp);

printf("数据追加完成!✅\n");

fclose(fp);

return 0;

}

4. 二进制文件读写:fread() & fwrite()

二进制文件(如图片、音频、自定义结构体数据)无法用文本函数读写,需用fread()和fwrite(),按 “块” 操作数据。

  • fread(buf, size, count, fp):从文件中读取count个大小为size的 “块”,存入buf;返回实际读取的块数(若小于count,可能到末尾或出错)。
  • fwrite(buf, size, count, fp):将buf中count个大小为size的 “块” 写入文件;返回实际写入的块数(若小于count,表示写入失败)。

示例(将结构体数据写入二进制文件,再读取出来):

#include 定义一个结构体(存储学生信息)

typedef struct {

char name[20];

int age;

float score;

} Student;

int main() {

Student stu1 = {"Zhang San", 20, 95.5};

Student stu2; // 用于存储读取的数据

FILE *fp = fopen("students.bin", "wb+"); // 二进制读写模式

if (fp == NULL) {

printf("文件打开失败!❌\n");

return 1;

}

// 写入结构体数据(1个块,大小为Student)

int write_count = fwrite(&stu1, sizeof(Student), 1, fp);

if (write_count == 1) {

printf("结构体写入成功!✅\n");

} else {

printf("结构体写入失败!❌\n");

fclose(fp);

return 1;

}

// 移动指针到文件开头,准备读取

rewind(fp);

// 读取结构体数据

int read_count = fread(&stu2, sizeof(Student), 1, fp);

if (read_count == 1) {

printf("读取到的学生信息:\n");

printf("姓名:%s\n年龄:%d\n分数:%.1f\n", stu2.name, stu2.age, stu2.score);

} else {

printf("结构体读取失败!❌\n");

}

fclose(fp);

return 0;

}

三、避坑指南:文件读写常见错误及解决方法 ⚠️

  1. 文件打开失败(返回 NULL)
    • 检查文件路径是否正确(相对路径是相对于程序运行目录,不是代码文件目录);
    • 检查文件权限(如只读文件用w模式打开会失败);
    • 检查磁盘空间是否充足(创建新文件时)。
  1. 读取到乱码或数据错误
    • 文本文件:确保读写模式与文件类型匹配(如二进制文件用文本模式读会乱码);
    • 二进制文件:确保fread()/fwrite()的size和count参数正确(与结构体大小一致)。
  1. 数据未写入文件
    • 忘记关闭文件(fclose()会强制刷新缓冲区,未关闭可能导致缓冲区数据未写入磁盘);
    • 缓冲区未刷新(可手动调用fflush(fp)强制刷新,但尽量用fclose())。
  1. 文件指针位置错误
    • 读写切换时,需用rewind(fp)(移到开头)、fseek()(指定位置)或ftell()(获取当前位置)调整指针,避免读写位置混乱。

四、总结

C 语言文件读写的核心是 “指针 + 函数 + 模式”:

  1. 用fopen()打开文件,获取文件指针,务必判断是否为NULL;
  1. 根据文件类型(文本 / 二进制)选择对应的读写函数(fgetc/fputs 或 fread/fwrite);
  1. 操作完成后,用fclose()关闭文件,释放资源;
  1. 注意处理边界情况(如文件末尾、操作失败),避免程序崩溃或数据丢失。

掌握这些内容后,你就能轻松应对 C 语言开发中的文件操作场景啦!如果有疑问,欢迎在评论区留言讨论~ 💬

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/11 1:55:07

互联网大厂Java面试:音视频场景下的技术栈深度解析

互联网大厂Java面试&#xff1a;音视频场景下的技术栈深度解析 场景设定 在一场互联网大厂的Java开发岗位面试中&#xff0c;面试官和水货程序员谢飞机展开了一场关于音视频场景的技术讨论。谢飞机虽有点小聪明&#xff0c;但面对复杂问题时常含糊其辞。 第一轮提问 1. 请简…

作者头像 李华
网站建设 2026/4/16 10:17:02

臭双非的技术学习之旅——Meta Quest3开发篇

嗨嗨嗨 知识点捏 这个部分其实很杂哼乱&#xff0c;没有一个系统的教学。我们以目前可公开的信息来统合我们的知识点 目前可公开的信息 Quest3 开发使用的是Mate已经研究出的一份较为完善的架构&#xff0c;可以在unity的资源商店里面找到all in one SDK &#xff0c;它提供了很…

作者头像 李华
网站建设 2026/4/16 10:13:37

YOLOv11改进 - C3k2融合 | C3k2融合Mona多认知视觉适配器(CVPR 2025):打破全参数微调的性能枷锁:即插即用的提点神器

前言 本文介绍了新型视觉适配器微调方法Mona,并将其集成到YOLOv11中。传统全参数微调成本高、存储负担重且有过拟合风险,现有PEFT方法性能落后。Mona仅调整5%以内的骨干网络参数,在多个视觉任务中超越全参数微调。其核心亮点包括参数效率高、性能突破和即插即用。适配器模块…

作者头像 李华
网站建设 2026/4/16 10:16:50

simulink中使用fft进行频谱分析卡死可能的解决方法

simulink中使用fft进行频谱分析卡死可能的解决方法 分析前需要确保的设置 在配置参数里面取消勾选单一仿真输出; 在Scope中打开将数据记录到工作区 检查数据维度, FFT工具箱仅仅能分析一维数据, 例如下图中左边为一维数据, 右边的为二维数据, 将右边的数据导入到MATLAB工作区进…

作者头像 李华
网站建设 2026/4/13 18:18:23

Dolby Atmos Lite:轻量级全景声音效模拟工具,多设备音效增强方案

Dolby Atmos Lite是一款专注于音效增强的轻量级工具&#xff0c;旨在通过算法模拟杜比全景声的沉浸式音频体验。该软件以其极小的体积和广泛的设备兼容性&#xff0c;为用户提供了简单的音效优化解决方案&#xff0c;特别适合希望在普通设备上获得更好音频体验的用户。 获取地…

作者头像 李华
网站建设 2026/4/15 16:49:47

python第一阶段第10章

1. 整体介绍1.1 数据来源2. 效果一&#xff1a; 折线图-----2020印美日新冠累计确诊人数2.1 json数据格式2.1.1 什么时json2.1.2 json有什么用2.1.3 json格式数据转化import json # 准备列表 &#xff0c;列表内每一个元素都是字典&#xff0c;将其转换为json data [{"na…

作者头像 李华