C语言文件操作指南:从打开关闭到读写实战

夏知夏
夏知夏
发布时间:2026-10-15 | 3人浏览过
原创

C程序运行时数据仅存于内存,退出后丢失。为实现数据持久化,需掌握C语言的文件操作机制。本文将解析文件类型与命名规则,演示如何通过fopen打开、fclose关闭文件,并利用fread、fwrite等函数完成数据的写入与读取。

数据持久化的必要性

在编写程序时,默认状态下所有数据存储在内存中。一旦程序运行结束或进程被终止,这些内存数据随即消失。这意味着下次启动程序时,必须重新录入所有信息,造成极大的不便。

为了解决这一痛点,我们需要引入文件的概念。通过将程序运行时产生的数据存储到磁盘中,可以实现跨会话的数据保留与调用。

文件基础概念

文件的分类

在程序设计中,文件主要分为两类:

  • 程序文件:包括源程序文件(.c)、目标文件(Windows环境下为.obj)以及可执行程序(.exe)。
  • 数据文件:内容不一定是程序代码,而是程序运行时需要读入或输出的数据。本次讲解主要聚焦于此,利用它将运行时数据保存至磁盘。

文件名的构成

完整的文件名由三个部分组成:文件路径 + 文件名主干 + 文件后缀。

例如:c:\code\test.txt。

文件的打开与关闭

文件指针与FILE结构

在C语言中,系统对文件的操作统一采用“流”的方式,并通过一个名为 FILE 的结构体来记录文件状态。该结构体由标准库声明,通常包含缓冲区指针、文件大小、读写标志等信息。我们无需深究其内部细节,只需理解它是一个用于控制文件流的句柄。

核心API:打开与关闭

要进行文件读写,首先必须打开文件。ANSI C 标准规定使用 fopen 函数:

FILE * fopen ( const char * filename, const char * mode );

参数说明:

  • filename:文件名或路径。
  • mode:打开模式,决定了允许进行的读写操作及文件不存在时的行为。

常用打开模式详解

模式含义文件不存在时
"r" (只读)打开已存在的文本文件进行输入出错
"w" (只写)输出数据,若存在则清空,若不存在则创建建立新文件
"a" (追加)向文件末尾添加数据建立新文件
"rb" / "wb" / "ab"对应上述模式的二进制版本同上
"r+" / "w+" / "a+"允许同时进行读写操作根据主体模式决定

注:在I/O语境中,“输入”指数据流向内存(读取),“输出”指数据流向文件(写入)。

完成读写任务后,务必使用 fclose 关闭文件,以释放资源并刷新缓冲区:

int fclose ( FILE * stream );

打开与关闭示例

#include <stdio.h>
int main ()
{
  FILE * pFile;
  // 1. 打开文件
  pFile = fopen ("myfile.txt","w");
  
  // 2. 检查是否成功打开
  if (pFile!=NULL)
  {
    fputs ("fopen example",pFile); // 写入数据
    // 3. 关闭文件
    fclose (pFile);
  }
  return 0; 
}

文件的读写操作

当文件正确打开后,即可使用相应的IO函数进行数据交互。常用的函数如下表所示:

功能函数名适用场景
字符输入fgetc所有输入流
字符输出fputc所有输出流
文本行输入fgets所有输入流
文本行输出fputs所有输出流
格式化输入fscanf所有输入流
格式化输出fprintf所有输出流
二进制输入fread文件
二进制输出fwrite文件

实战案例:通讯录数据的保存与加载

以下是一个完整的工程应用示例,展示了如何定义数据结构,并使用二进制方式将通讯录数据保存到文件,以及如何从文件中恢复数据。这种方法效率高,且能精确还原复杂结构体。

// 假设已经定义了联系人结构体和通讯录结构
// struct contact_person { ... };
// typedef struct Contact { ... } Contact;

1. 保存数据 (Save)

目的:将内存中的通讯录数据整体写入磁盘文件。

void Save(Contact* con) 
{
    // 以二进制写模式打开
    FILE* fp = fopen("contact.txt", "wb");
    if (fp == NULL)
    {
        printf("Save()::%s", strerror(errno)); 
        return;
    }
    else
    {
        // fwrite: 写入 count 个大小为 sizeof(struct contact_person) 的数据块
        fwrite(con->data, sizeof(struct contact_person), con->count, fp);
    }
    fclose(fp); // 关闭并刷新
    fp = NULL;
}

2. 加载数据 (Load)

目的:读取文件内容,按顺序填充至内存结构体中。

void Load(Contact* con) 
{
    // 以二进制读模式打开
    FILE* fp = fopen("contact.txt", "rb"); // 注意读取二进制文件建议用 rb
    if (fp == NULL)
    {
        printf("Load()::%s", strerror(errno));
        return;
    }
    else
    {
        struct contact_person tmp;
        // fread 返回成功读取的数据项个数
        while (fread(&amp;tmp, sizeof(struct contact_person), 1, fp)) 
        {
            Check_capacity(con); // 确保容量足够
            con->data[con->count] = tmp; // 存入数组
            con->count++;              // 更新计数
        }
    }
    fclose(fp);
    fp = NULL;
}

上述代码清晰地展示了如何利用 fread 的返回值判断读取是否结束,是处理定长结构体序列的标准做法。

总结

C语言的文件操作核心在于管理 FILE* 指针的生命周期。遵循“先打开、后操作、最后关闭”的原则,根据业务需求选择正确的打开模式(如文本 vs 二进制)及读写函数,即可高效地解决数据持久化问题。

以上就是C语言文件操作方法与读写函数的详细内容,更多关于C语言文件操作技巧的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表