news 2026/2/17 20:03:57

初识C语言(文件操作)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
初识C语言(文件操作)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
    • 本文主要讲解文件操作相关的知识。
  • 一、文件是什么?
    • 1.文件的作用与分类
    • 2.文件名结构
    • 3.二进制文件与文本文件
    • 4.数据文件的应用场景
  • 二、文件的打开和关闭(C语言)
    • 1. 文件打开(fopen函数)
      • 基本语法
      • 参数说明
      • 常用打开模式
      • 二进制文件模式
      • 返回值
      • 示例代码
    • 2. 文件关闭(fclose函数)
      • 基本语法
      • 参数说明
      • 返回值
      • 示例代码
    • 3. 注意事项
    • 4. 完整示例
    • 5. 常见问题
  • 三、文件的顺序读写
    • 1. 基本概念
    • 2. 顺序读写的函数
      • 2.1 字符读写
      • 2.2 字符串读写
      • 2.3 格式化读写
    • 3. 应用示例
      • 3.1 文件复制
      • 3.2 日志记录
    • 4. 注意事项
    • 5. 性能考虑
  • 四、文件的随机读写
    • 1. 文件指针的概念
    • 2. 文件指针定位函数
      • fseek函数
      • ftell函数
      • rewind函数
    • 3. 随机读写示例
      • 示例1:读取文件中间部分内容
      • 示例2:修改二进制文件中的特定记录
    • 4. 注意事项
  • 五、文件缓冲区(C语言)
    • 1. 缓冲区的概念与作用
    • 2. 缓冲区的类型
    • 3. 缓冲区相关函数
    • 4. 缓冲区使用注意事项
    • 5. 缓冲区示例代码
  • 六、更新文件(C语言)
    • 1. 文件更新概述
    • 2. 基本操作函数
      • 2.1 fopen()函数
      • 2.2 fseek()函数
    • 3. 常见更新操作示例
      • 3.1 追加内容
      • 3.2 修改指定位置内容
      • 3.3 插入内容
    • 4. 注意事项
    • 5. 高级技巧
      • 5.1 内存映射文件
      • 5.2 事务处理
    • 6. 实际应用场景
  • 总结

前言

本文主要讲解文件操作相关的知识。

一、文件是什么?

1.文件的作用与分类

持久化存储数据
程序运行时产生的数据存储在内存中,程序退出后内存被回收,数据丢失。文件将数据保存到磁盘(硬盘),实现数据的持久化存储,确保程序多次运行时可访问历史数据。

文件的分类
从功能角度分为程序文件和数据文件:

  • 程序文件:包括源代码(.c)、目标文件(.obj)、可执行程序(.exe)。
  • 数据文件:存储程序运行时读写的数据,如输入数据或输出结果。本章重点讨论数据文件。

2.文件名结构

文件标识由三部分组成,例如c:\code\test.txt

  • 文件路径c:\code\
  • 文件名主干test
  • 文件后缀.txt

3.二进制文件与文本文件

根据数据组织形式分为两类:

  • 文本文件:以ASCII码存储字符数据。例如整数10000以ASCII形式存储占5字节(每个字符1字节)。
  • 二进制文件:直接以内存中的二进制形式存储数据。同一整数10000仅占4字节(按整型存储)。

存储差异示例

  • 文本文件:字符按ASCII存储,数值可转为ASCII或二进制。
  • 二进制文件:数据无转换,存储紧凑,效率更高。

4.数据文件的应用场景

  • 终端交互:默认从键盘输入、输出到显示器。
  • 磁盘文件:需长期保存或大量数据时,读写磁盘文件更高效。

二、文件的打开和关闭(C语言)

在C语言中,文件操作是程序与外部存储设备交互的重要方式。要操作文件,首先需要打开文件,操作完成后需要关闭文件。以下是关于文件打开和关闭的详细说明:

1. 文件打开(fopen函数)

基本语法

FILE*fopen(constchar*filename,constchar*mode);

参数说明

  • filename:要打开的文件名(包含路径)
  • mode:打开模式,指定文件的操作方式

常用打开模式

模式描述文件存在文件不存在
“r”只读打开成功返回NULL
“w”只写清空内容创建新文件
“a”追加追加内容创建新文件
“r+”读写打开成功返回NULL
“w+”读写清空内容创建新文件
“a+”读写追加内容创建新文件

二进制文件模式

在以上模式后加"b"表示二进制模式,如"rb"、"wb+"等

返回值

  • 成功:返回FILE指针(文件指针)
  • 失败:返回NULL

示例代码

FILE*fp;fp=fopen("example.txt","r");if(fp==NULL){printf("文件打开失败\n");exit(1);// 退出程序}

2. 文件关闭(fclose函数)

基本语法

intfclose(FILE*stream);

参数说明

  • stream:要关闭的文件指针

返回值

  • 成功:返回0
  • 失败:返回EOF(-1)

示例代码

if(fclose(fp)!=0){printf("文件关闭失败\n");}

3. 注意事项

  1. 错误处理:每次打开文件后都应检查返回值是否为NULL
  2. 资源释放:打开的文件必须关闭,否则可能导致资源泄露
  3. 缓冲区刷新:fclose会刷新缓冲区,确保数据写入文件
  4. 路径表示:Windows中使用"\“或”/“表示路径,如"C:\data\file.txt”

4. 完整示例

#include<stdio.h>#include<stdlib.h>intmain(){FILE*fp;// 打开文件fp=fopen("data.txt","w");if(fp==NULL){printf("无法创建文件\n");return1;}// 文件操作...fprintf(fp,"这是写入文件的内容\n");// 关闭文件if(fclose(fp)!=0){printf("文件关闭出错\n");return1;}return0;}

5. 常见问题

  1. 权限问题:如果没有写权限,以写模式打开文件会失败
  2. 文件锁定:某些系统会锁定正在使用的文件
  3. 路径问题:相对路径是相对于程序运行时的当前目录
  4. 缓冲区问题:未关闭文件可能导致数据未完全写入

三、文件的顺序读写

1. 基本概念

顺序读写是指按照文件中数据的物理存储顺序依次进行读写操作。与随机读写不同,顺序读写每次操作都会从当前位置开始,完成后文件指针会自动移动到下一个位置。

2. 顺序读写的函数

C语言提供了多个用于顺序读写文件的函数:

2.1 字符读写

  • fgetc(): 从文件中读取一个字符
    intch=fgetc(fp);// fp为文件指针
  • fputc(): 向文件写入一个字符
    fputc('A',fp);// 向文件写入字符'A'

2.2 字符串读写

  • fgets(): 从文件中读取一行字符串
    charstr[100];fgets(str,100,fp);// 最多读取99个字符
  • fputs(): 向文件写入字符串
    fputs("Hello World",fp);

2.3 格式化读写

  • fscanf(): 从文件格式化读取
    intage;fscanf(fp,"%d",&age);// 从文件读取整数
  • fprintf(): 向文件格式化写入
    fprintf(fp,"Name: %s, Age: %d","John",25);

3. 应用示例

3.1 文件复制

#include<stdio.h>intmain(){FILE*src=fopen("source.txt","r");FILE*dest=fopen("dest.txt","w");if(src==NULL||dest==NULL){printf("文件打开失败");return1;}intch;while((ch=fgetc(src))!=EOF){fputc(ch,dest);}fclose(src);fclose(dest);return0;}

3.2 日志记录

#include<stdio.h>#include<time.h>voidlog_message(constchar*msg){FILE*log=fopen("app.log","a");if(log==NULL)return;time_tnow;time(&now);fprintf(log,"[%s] %s\n",ctime(&now),msg);fclose(log);}

4. 注意事项

  1. 每次读写操作后,文件指针会自动后移
  2. 到达文件末尾时,fgetc()会返回EOF
  3. 打开文件后必须检查文件指针是否为NULL
  4. 操作完成后必须调用fclose()关闭文件
  5. 对于文本文件,不同操作系统可能有不同的换行符表示方式

5. 性能考虑

  • 对于大文件,逐个字符读写效率较低
  • 可以考虑使用缓冲区或块读写提高性能
  • 频繁打开关闭文件会影响性能,应尽量减少操作次数

四、文件的随机读写

1. 文件指针的概念

文件指针是一个指示当前读写位置的标记,它记录了在文件中进行操作的位置。在随机读写文件时,我们需要通过移动文件指针来定位到特定的位置进行操作。

文件指针具有以下特性:

  1. 打开文件时,指针默认指向文件开头(位置0)
  2. 每次读写操作后,指针会自动移动到下一个位置
  3. 可以通过特定函数手动移动指针位置

2. 文件指针定位函数

fseek函数

intfseek(FILE*stream,longoffset,intorigin);
  • 参数说明:
    • stream:文件指针
    • offset:偏移量(字节数),可正可负
    • origin:基准位置,可取以下值:
      • SEEK_SET:文件开头
      • SEEK_CUR:当前位置
      • SEEK_END:文件末尾

示例:

fseek(fp,10,SEEK_SET);// 将指针移动到距文件开头10字节处fseek(fp,-5,SEEK_END);// 将指针移动到距文件末尾前5字节处

ftell函数

longftell(FILE*stream);

返回当前文件指针的位置(相对于文件开头的字节偏移量)

示例:

longpos=ftell(fp);// 获取当前指针位置

rewind函数

voidrewind(FILE*stream);

将文件指针重置到文件开头,相当于:

fseek(fp,0,SEEK_SET);

3. 随机读写示例

示例1:读取文件中间部分内容

FILE*fp=fopen("data.txt","r");if(fp==NULL){perror("文件打开失败");return;}// 定位到文件中间位置fseek(fp,0,SEEK_END);longsize=ftell(fp);fseek(fp,size/2,SEEK_SET);// 读取中间部分内容charbuffer[100];fread(buffer,1,50,fp);fclose(fp);

示例2:修改二进制文件中的特定记录

typedefstruct{intid;charname[20];floatscore;}Student;// 修改第3条记录的成绩FILE*fp=fopen("students.dat","r+");if(fp==NULL){perror("文件打开失败");return;}// 定位到第3条记录fseek(fp,2*sizeof(Student),SEEK_SET);Student stu;fread(&stu,sizeof(Student),1,fp);// 修改成绩stu.score=95.5;// 写回文件fseek(fp,2*sizeof(Student),SEEK_SET);fwrite(&stu,sizeof(Student),1,fp);fclose(fp);

4. 注意事项

  1. 二进制文件与文本文件:

    • 文本文件的随机读写可能会因系统不同而产生差异
    • 二进制文件的随机读写更加可靠
  2. 边界检查:

    • 移动指针时要注意不要超出文件范围
    • 可以使用ftell和fseek结合检查文件大小
  3. 错误处理:

    • 检查fseek的返回值(成功返回0,失败返回非0)
    • 处理可能的文件定位错误
  4. 性能考虑:

    • 频繁的随机访问可能会降低IO性能
    • 对于大量随机访问,考虑使用内存缓存

五、文件缓冲区(C语言)

1. 缓冲区的概念与作用

文件缓冲区是内存中的一块区域,用于临时存储文件读写的数据。缓冲区的主要作用包括:

  1. 提高I/O效率:减少直接访问磁盘的次数,通过批量读写提高性能
  2. 协调速度差异:解决CPU处理速度与磁盘I/O速度不匹配的问题
  3. 数据暂存:为流式I/O操作提供数据中转站

示例场景:当程序调用fwrite()写入100字节数据时,数据不会立即写入磁盘,而是先存入缓冲区,待缓冲区满或显式刷新时才执行实际磁盘写入。

2. 缓冲区的类型

C语言中主要有三种缓冲模式:

  1. 全缓冲(Fully Buffered)

    • 缓冲区满时才执行实际I/O操作
    • 典型应用:普通文件读写
    • 缓冲区大小通常为BUFSIZ(在stdio.h中定义,通常为512或4096字节)
  2. 行缓冲(Line Buffered)

    • 遇到换行符’\n’或缓冲区满时刷新
    • 典型应用:终端I/O(stdin/stdout)
    • 示例:printf()输出通常会在遇到\n或程序正常结束时自动刷新
  3. 无缓冲(Unbuffered)

    • 立即执行I/O操作
    • 典型应用:stderr错误输出
    • 示例:perror()会立即将错误信息输出到屏幕

3. 缓冲区相关函数

  1. 设置缓冲模式

    intsetvbuf(FILE*stream,char*buf,intmode,size_tsize);
    • 参数说明:
      • stream:文件指针
      • buf:用户提供的缓冲区(为NULL时由库自动分配)
      • mode:_IOFBF(全缓冲)/_IOLBF(行缓冲)/_IONBF(无缓冲)
      • size:缓冲区大小
  2. 强制刷新缓冲区

    intfflush(FILE*stream);
    • 将缓冲区内容立即写入文件
    • stream为NULL时刷新所有输出流
  3. 关闭文件时的自动刷新

    intfclose(FILE*stream);
    • 关闭文件前会自动调用fflush()
    • 示例:程序异常终止时可能丢失未刷新的缓冲区数据

4. 缓冲区使用注意事项

  1. 数据一致性问题

    • 重要数据应及时fflush(),防止程序崩溃导致数据丢失
    • 示例:数据库日志记录应先fflush()再执行关键操作
  2. 性能调优

    • 大文件处理时可适当增大缓冲区提高性能
    • 示例:视频处理程序可设置8KB或更大的缓冲区
  3. 跨平台差异

    • 不同系统下默认缓冲区大小可能不同
    • 示例:Windows和Linux的BUFSIZ可能不同
  4. 线程安全

    • 多线程环境下操作同一文件需加锁保护
    • 示例:使用flockfile()/funlockfile()函数族

5. 缓冲区示例代码

#include<stdio.h>#include<stdlib.h>intmain(){FILE*fp=fopen("test.dat","w");if(!fp){perror("fopen failed");returnEXIT_FAILURE;}// 设置8KB的全缓冲区charbuf[8192];if(setvbuf(fp,buf,_IOFBF,sizeof(buf))!=0){perror("setvbuf failed");fclose(fp);returnEXIT_FAILURE;}// 写入数据(先存入缓冲区)for(inti=0;i<1000;i++){fprintf(fp,"Record %d\n",i);}// 强制刷新缓冲区fflush(fp);// 修改为行缓冲模式setvbuf(fp,NULL,_IOLBF,0);fprintf(fp,"This will be line buffered\n");fclose(fp);returnEXIT_SUCCESS;}

六、更新文件(C语言)

1. 文件更新概述

在C语言中,文件更新操作主要包括以下几种方式:

  • 追加内容到文件末尾
  • 修改文件中特定位置的内容
  • 替换文件中的部分内容
  • 插入新内容到文件指定位置

2. 基本操作函数

2.1 fopen()函数

FILE*fopen(constchar*filename,constchar*mode);

常用打开模式:

  • “r”:只读
  • “w”:只写(会清空原文件)
  • “a”:追加(在文件末尾写入)
  • “r+”:读写(从文件头开始)
  • “w+”:读写(清空原文件)
  • “a+”:读写(从文件末尾开始)

2.2 fseek()函数

intfseek(FILE*stream,longoffset,intwhence);

参数说明:

  • whence取值:
    • SEEK_SET:从文件头开始
    • SEEK_CUR:从当前位置开始
    • SEEK_END:从文件末尾开始

3. 常见更新操作示例

3.1 追加内容

FILE*fp=fopen("example.txt","a");if(fp!=NULL){fprintf(fp,"This will be appended to the end.\n");fclose(fp);}

3.2 修改指定位置内容

FILE*fp=fopen("example.dat","r+");if(fp!=NULL){fseek(fp,10,SEEK_SET);// 定位到第10字节fwrite("new data",1,8,fp);// 写入8字节新数据fclose(fp);}

3.3 插入内容

// 1. 打开源文件和临时文件FILE*src=fopen("source.txt","r");FILE*tmp=fopen("temp.txt","w");// 2. 复制前半部分到临时文件intpos=0;while(pos<insert_position){intch=fgetc(src);fputc(ch,tmp);pos++;}// 3. 写入要插入的内容fputs("New inserted content\n",tmp);// 4. 复制剩余部分intch;while((ch=fgetc(src))!=EOF){fputc(ch,tmp);}// 5. 关闭文件并替换fclose(src);fclose(tmp);remove("source.txt");rename("temp.txt","source.txt");

4. 注意事项

  1. 错误处理:所有文件操作都应检查返回值
  2. 缓冲区刷新:必要时使用fflush()确保数据写入
  3. 文件锁定:在多进程/线程环境中可能需要文件锁定
  4. 性能考虑:频繁的小规模更新可能影响性能

5. 高级技巧

5.1 内存映射文件

对于大文件更新,可以使用内存映射提高效率:

#include<sys/mman.h>// 使用mmap()函数将文件映射到内存

5.2 事务处理

实现简单的文件更新事务:

  1. 创建临时文件
  2. 执行所有更新操作
  3. 确认无误后替换原文件
  4. 出现错误则回滚

6. 实际应用场景

  1. 日志文件更新:追加新日志记录
  2. 配置文件修改:更新特定配置项
  3. 数据库操作:修改数据记录
  4. 游戏存档:更新玩家进度

总结

文件操作对于信息的储存和再利用非常重要。

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

实时异常检测是如何实现的?工业Agent数据分析中的5个核心算法揭秘

第一章&#xff1a;实时异常检测是如何实现的&#xff1f;工业Agent数据分析中的5个核心算法揭秘在现代工业物联网&#xff08;IIoT&#xff09;系统中&#xff0c;实时异常检测是保障生产连续性与设备健康的关键能力。通过部署在边缘设备或云端的智能Agent&#xff0c;系统能够…

作者头像 李华
网站建设 2026/2/13 15:38:34

学生轻薄本电脑推荐/哪家好:适合学生使用的轻薄型笔记本电脑全面解析

在当今数字化学习环境中&#xff0c;一款适合学生使用的轻薄型笔记本电脑已成为不可或缺的学习工具。面对市场上琳琅满目的产品&#xff0c;如何选择一款真正适合自己的轻薄本&#xff1f;本文将为您提供客观、实用的选购指南&#xff0c;帮助您找到最适合的轻薄本。选择学生轻…

作者头像 李华
网站建设 2026/2/17 17:49:10

2025各大品牌学生游戏本电脑推荐及其散热性能对比

引言随着2025年游戏产业的蓬勃发展&#xff0c;高性能游戏本已成为学生群体的刚需装备。在兼顾学习、娱乐与创作的多重需求下&#xff0c;散热性能成为影响用户体验的关键指标。本文基于2025年12月的市场数据与实际测试&#xff0c;对主流品牌学生游戏本进行客观推荐与散热性能…

作者头像 李华
网站建设 2026/2/16 15:40:30

【资深工程师亲授】:构建懂交规的自动驾驶Agent的5个关键步骤

第一章&#xff1a;自动驾驶Agent与交通规则的融合挑战自动驾驶技术的发展正推动交通系统向智能化演进&#xff0c;然而将自动驾驶Agent&#xff08;Autonomous Agent&#xff09;与现实世界复杂的交通规则体系深度融合&#xff0c;仍面临多重挑战。交通规则不仅是静态的法规条…

作者头像 李华
网站建设 2026/2/16 20:41:45

为什么90%的农场主都用错了施肥算法?揭秘农业Agent背后的科学逻辑

第一章&#xff1a;农业种植 Agent 的施肥量在现代农业智能化系统中&#xff0c;农业种植 Agent 通过感知环境数据与作物生长状态&#xff0c;动态决策最优施肥量。该过程融合土壤养分检测、气象信息及作物需肥规律&#xff0c;实现精准农业管理。施肥决策的数据输入 Agent 的施…

作者头像 李华
网站建设 2026/2/14 11:34:39

DevOps:开发运维一体化的未来之路

一、DevOps概念基本概念在如今互联网的格局下&#xff0c;抢占市场变得尤为重要&#xff0c;因此**敏捷开发**越来越被大家所推崇。于是&#xff0c;慢慢的有了DevOps这个概念&#xff0c;含义就是**开发-运维一体化**&#xff0c;能够理顺开发和运维之间相互配合关系的任何事物…

作者头像 李华