C语言文件操作

1、为什么使用文件

2、什么是文件

3、二进制文件和文本文件

4、文件的打开和关闭

5、文件的顺序

6、文件的随机读写

7、文件读取结束的判定

8、文件缓冲区

int main()

{

int a = 0;

scanf("%d", &a); // 这个就是将输入的数字放入文件中

printf("%d\n", a);

return 0;

}

一、问什么使用文件

  • 内存数据断电丢失,文件可永久保存数据
  • 方便数据重复读取、批量处理;
  • 实现多程序数据共享。

二、什么是文件

磁盘(硬盘)上的文件是文件,但是在程序设计中,我们一般谈到的文件有两种:程序文件、数据文件

程序文件:

源程序文件(.c

  • 后缀:.c

    目标文件(.obj / .o

  • 后缀:Windows 下.obj,Linux 下.o

    可执行文件(.exe

  • 后缀:Windows 系统下 .exe

数据文件

专门用来存放程序运行所需数据的文件,不包含代码指令。作用:给程序提供输入数据、保存程序运行结果,实现数据长久存储。

本章讨论的是数据文件

在以前各章所处理数据的输入和输出都是以终端为对象的,即从终端的键盘输入数据并行结果显示在显示器上,其实有的时候我们会把信息输出到磁盘上,当需要的时候再从磁盘上把数据读到内存中,使用这里处理的就是磁盘上的文件。

文件名:

一个文件要有一个唯一的文件标识,以便用户识别和引用。文件名包含三个部分,**文件路径 + 文件名主干 + 文件后缀(扩展名);例如:**E:\project\main.c为了方便起见,文件标识常被称为文件名。

二进制文件和文本文件

文本文件(ASCII 文件)

1. 存储规则

每一个字符 按它对应的 ASCII 码 存储,内容就是我们能看懂的文字、数字、符号。

2. 特点

  1. 可用记事本、写字板直接打开阅读、编辑;
  2. \nEOF(-1) 作为结束标志;
  3. 占用空间略大,读写速度稍慢;
  4. 适合存放文字、普通数据。

二进制文件

1. 存储规则

数据直接按照内存中的二进制原样保存,不转换成 ASCII 字符。

2. 特点

  1. 记事本打开显示乱码,只能由对应程序读取;
  2. 存储紧凑、占用空间小、读写速度快
  3. 原样保存变量、结构体、数组,适合存大批量数据、自定义类型;
  4. 没有专门的换行分隔符。

流和标准流

我们程序的数据需要输出到各种外部设备,也需要从外部设备获取数据,不同的外部设备的输入、输出操作各不相同,为了方便程序员对各种设备进行方便的操作,我们抽象出了流的概念。我们可以把流想象成流淌着的字符的河流。c 程序针对文件、画面、键盘等的数据输入,输出的操作都是通过流操作的,一般情况下我们想要向流里写数据,或者从流中读取数据,都要打开流,然后操作。

标准流

那为什么我们从键盘输入数据,向屏幕上输出数据并没有打开流?那是因为 c 语言程序在启动的时候默认打开了三个流:

  • stdin 标准输入流 → 绑定键盘,scanf函数就是从标准输入流中读取数据的
  • stdout 标准输出流 → 绑定显示器,printf函数就是将信息输出到标准输出流中
  • stderr 标准错误流 → 绑定显示器,大多数环境中输出到显示器界面

这默认打开了这三个流,我们使用 scanf、printf 的函数就可以直接进行输入,输出操作的。stdin、stdout、stder三个流是类型是:FILE*,通常称为文件指针。 C 语言通过 FILE 文件指针 管理流。

文件的打开和关闭

文件在读写之前应该先打开文件,在使用结束之后应该关闭文件。在编写程序的时候,在打开文件的同时都会返回一个 FILE*的指针变量指向该文件,也相当于建立了指针和文件的关系。

fclose

复制代码
语法:int fclose ( FILE * stream );
  • 头文件:#include <stdio.h>
  • 形参:文件指针 (必须是已经通过 fopen 成功打开的指针)
  • 返回值:
    • 关闭成功 :返回 0
    • 关闭失败 :返回 非 0 值

功能 关闭形参 stream 所关联的文件,解除文件指针和文件之间的关联

  1. 解除内部缓冲区与流的绑定;
  2. 刷新输出缓冲区 :缓冲区里还没写到磁盘的数据,全部写入文件(防止数据丢失);
  3. 清空输入缓冲区:缓冲区中还未读取的数据,直接丢弃。
  1. 参数FILE * 类型的流 / 文件指针。
  2. 返回值 :成功返回 0,失败返回非 0 值。

文件的顺序读写:

表格

函数名 函数原型 核心功能 关键参数 返回值 高频考点
fopen FILE *fopen (char *filename, char *mode); 打开文件,建立文件指针与文件的关联 filename:文件路径 / 名 mode:打开方式 成功:返回文件FILE*指针 失败:返回NULL 必须判断打开是否成功;路径转义符\\;打开方式的选用
fclose int fclose (FILE *stream); 关闭文件,解除指针与文件的关联,刷新缓冲区 stream:已打开的文件指针 成功:返回0 失败:返回非 0 值 必须配合fopen使用;防止数据丢失;释放系统资源
fprintf int fprintf (FILE*stream, char *format, 输出列表); 文本文件顺序写入,按格式将内存数据写入文件 stream:文件指针format:格式控制串 成功:返回写入的字符数 失败:返回负数 文本文件写专用;用法和printf几乎一致,仅多文件指针参数
fscanf int fscanf (FILE*stream, char *format, 地址列表); 文本文件顺序读取,从文件读取数据存入内存变量 stream:文件指针format:格式控制串 成功:返回成功读取的变量数失败 / 到文件尾:返回EOF 文本文件读专用;变量必须加&;和scanf用法一致
fwrite int fwrite (void *ptr, int size, int count, FILE *stream); 二进制文件顺序写入,按字节块写入数据 ptr:数据首地址size:单个数据字节数count:数据个数 成功:返回实际写入的完整数据块数 二进制文件写专用;适合数组 / 结构体 / 大批量数据
fread int fread (void *ptr, int size, int count, FILE *stream); 二进制文件顺序读取,按字节块读取数据 ptr:接收数据的内存地址其余参数同fwrite 成功:返回实际读取的完整数据块数 二进制文件读专用;和fwrite配对使用

表格

流名称 系统预设指针 对应设备 核心作用 常用函数
标准输入流 stdin 键盘 从键盘读取数据,输入到程序中 scanfgetcharfscanf(stdin,...)
标准输出流 stdout 显示器 把程序数据输出到屏幕上 printfputcharfprintf(stdout,...)
标准错误流 stderr 显示器 专门输出程序的错误、警告信息 报错提示专用

表格

打开方式 含义 核心规则 适用场景
r 只读(文本文件) 文件必须存在,否则打开失败;只能读,不能写 读取已有的文本文件数据
w 只写(文本文件) 文件不存在则新建;文件存在则清空原有全部内容,再写入 新建文本文件、覆盖原有文件内容
a 追加(文本文件) 文件不存在则新建;文件存在则在末尾续写内容,不覆盖原有数据 在已有文本文件末尾添加新内容
rb 只读(二进制文件) r,仅针对二进制文件 读取已有的二进制文件数据
wb 只写(二进制文件) w,仅针对二进制文件 新建 / 覆盖二进制文件
ab 追加(二进制文件) a,仅针对二进制文件 在二进制文件末尾续写内容

feof和ferror

表格

函数 原型 功能 返回值 使用场景
feof int feof(FILE *fp); 判断是否到达文件末尾 到文件尾:返回非 0 未到尾:返回0 循环读文件,判断是否读完
ferror int ferror(FILE *fp); 判断文件读写是否出错 出错:返回非 0 正常:返回0 检测读写过程

fputs和fgets

表格

函数 功能 原型 适用文件 核心特点
fputs 向文件写入字符串 int fputs(char *str, FILE *fp); 文本文件 不自动加换行、\0 不写入文件
fgets 从文件读取字符串 char *fgets(char *str, int n, FILE *fp); 文本文件 最多读 n-1 个字符;读到 \n 会一并存入;遇文件尾返回NULL

规则总览

  1. 正常读到 换行符 \n
    • 只要还没读满 n-1 位,会把 \n 一并存入数组
    • 然后自动追加 \0 作为字符串结束。
  2. 未遇到 \n,但字符数达到 n-1
    • 停止读取,不接收后续字符,也不收 \n
    • 末尾直接补 \0
  3. 读到文件末尾:返回 NULL

对比一组函数

一、输入类函数对比(scanf /fscanf/sscanf)

表格

函数名称 核心功能 标准函数原型 核心输入源 适用场景 核心特点 返回值规则 高频考点 / 易错点
scanf 标准输入流读取格式化数据 int scanf (const char *format, 地址列表); 键盘(终端) 日常程序的终端手动输入、控制台数据读取 1. 系统自动打开标准输入流,无需手动开关 2. 输入数据以空格 / 回车 / 制表符分隔 3. 是最基础、最常用的输入函数 成功:返回成功读取的变量个数 失败 / 输入结束:返回 EOF(-1) 1. 读取变量必须加取地址符&(最常考易错点) 2. 格式符必须与变量类型严格匹配 3. 无法读取带空格的完整字符串
fscanf 文件流读取格式化数据 int fscanf (FILE *fp, const char *format, 地址列表); 磁盘文本文件 从已打开的文本文件中读取数据、文件内容解析 1. 必须先通过fopen打开文件,获取有效文件指针fp 2. 用法与scanf几乎完全一致,仅多 1 个文件指针参数3. 按文件内容顺序读取,文件指针自动后移 成功:返回成功读取的变量个数 失败 / 到文件末尾:返回 EOF(-1) 1. 必须先判断文件是否打开成功(fp == NULL) 2. 仅适用于文本文件,二进制文件不推荐使用 3. 读取结束后必须用fclose关闭文件
sscanf 内存字符串中读取格式化数据 int sscanf (const char *str, const char *format, 地址列表); 内存中的字符数组 / 字符串常量 字符串解析、从已有字符串中提取指定格式数据、字符串拆分 1. 输入源是内存里的字符串,不涉及键盘 / 文件操作 2. 不会修改原字符串,仅从其中读取数据3. 可实现复杂的字符串格式提取,是字符串处理高频函数 成功:返回成功读取的变量个数 失败 / 字符串结束:返回 EOF(-1) 1. 第一个参数是字符串首地址,不是文件指针 2. 原字符串必须以\0结尾,否则会读取越界 3. 常与sprintf配对使用,实现字符串的格式化读写

二、输出类函数对比(printf /fprintf/sprintf)

表格

函数名称 核心功能 标准函数原型 核心输出目标 适用场景 核心特点 返回值规则 高频考点 / 易错点
printf 标准输出流输出格式化数据 int printf(const char *format, 输出列表); 显示器(终端屏幕) 日常程序的控制台结果输出、调试信息打印 1. 系统自动打开标准输出流,无需手动开关 2. 是最基础、最常用的输出函数 3. 输出内容直接显示在终端屏幕上 成功:返回成功输出的字符总数 失败:返回负数 1. 格式符必须与输出变量类型严格匹配2. 输出字符串时,数组名 / 指针无需加&3. 可通过\n实现换行、\t实现制表对齐
fprintf 文件流输出格式化数据 int fprintf(FILE *fp, const char *format, 输出列表); 磁盘文本文件 向已打开的文本文件写入数据、生成带格式的文本文件 1. 必须先通过fopen打开文件,获取有效文件指针fp 2. 用法与printf几乎完全一致,仅多 1 个文件指针参数 3. 按顺序写入文件,文件指针自动后移 成功:返回成功写入的字符总数 失败:返回负数 1. 必须先判断文件是否打开成功(fp == NULL) 2. 仅适用于文本文件,二进制文件不推荐使用 3. 写入结束后必须用fclose关闭文件,否则数据可能丢失
sprintf 内存字符串输出格式化数据 int sprintf (char *str, const char *format, 输出列表); 内存中的字符数组 字符串拼接、格式化生成新字符串、数字转字符串、字符串组装 1. 输出目标是内存里的字符数组,不涉及屏幕 / 文件操作 2. 自动在生成的字符串末尾添加结束符\0 3. 可实现复杂的字符串格式化拼接,是字符串处理高频函数 成功:返回成功写入的字符总数 (不含末尾的\0)失败:返回负数 1. 第一个参数是目标字符数组首地址,不是文件指针 2. 目标数组必须足够大,否则会造成缓冲区溢出(核心易错点) 3. 常与sscanf配对使用,实现字符串的格式化读写

文件的随机读写

基本概念

  1. 顺序读写:从文件开头往后依次读写,文件指针只能向后移动,不能跳转。
  2. 随机读写 :可人为移动文件指针,直接跳到文件任意位置读写,不用从头开始读。
  • 核心:靠 文件位置指针定位
  • 适用:二进制文件、结构体、数组(考试重点)

注意:随机读写一般搭配 二进制文件rb/wb),文本文件很少用。

表格

函数 功能 原型
fseek 移动文件位置指针(定位) int fseek(FILE *fp, long offset, int origin);
ftell 获取当前指针距离文件开头的字节数 long ftell(FILE *fp);
rewind 把指针重置到文件开头 void rewind(FILE *fp);

1. rewind () 重置文件指针到开头

1)功能

将文件位置指针直接跳回文件起始位置

2)语法

复制代码
rewind(FILE *fp);
  • 无返回值,无额外参数。

3)使用场景

读完一遍文件后,想从头再读一次 ,不用重新 fopen

示例

复制代码
rewind(fp);  // 指针回到文件开头

2. ftell () 获取当前指针位置

1)功能

计算当前文件指针 距离文件首部的字节数,返回字节偏移量。

2)语法

复制代码
long ftell(FILE *fp);
  • 返回值:long 类型,当前偏移字节数。

3)典型用途

文件总大小

复制代码
// 1.指针移到文件末尾
fseek(fp, 0, SEEK_END);
// 2.获取总字节数
long size = ftell(fp);
printf("文件大小:%ld 字节\n", size);

3. fseek () 重点(随机读写核心)

1)函数原型

复制代码
int fseek(FILE *fp, long offset, int origin);

三个参数逐个拆解(必背

参数 1:FILE *fp

已打开的文件指针(一般二进制文件 rb/wb

参数 2:long offset 偏移量
  • 正数:向文件尾部 向后移动
  • 负数:向文件头部 向前移动
  • 单位:字节
参数 3:int origin 参考起点(三种固定宏,必须记)

表格

宏名 数值 参考位置
SEEK_SET 0 文件开头(最常用)
SEEK_CUR 1 当前指针位置
SEEK_END 2 文件末尾

2)组合写法(高频定位)

  1. 文件开头向后移 10 字节

    fseek(fp, 10, SEEK_SET);

  2. 当前位置向后移 5 字节

    fseek(fp, 5, SEEK_CUR);

  3. 文件末尾向前移 8 字节(读最后一段数据)

    fseek(fp, -8, SEEK_END);

  4. 等价于 rewind(回到开头)

    fseek(fp, 0, SEEK_SET);

3)返回值

  • 定位成功:返回 0
  • 定位失败:返回 非 0 值

文件缓冲区

相关推荐
caimouse1 小时前
Reactos 第 9 章 设备驱动 — 9.4 内核劳务线程
开发语言·windows
Doker 多克1 小时前
Spring AI Alibaba—快速构建ReactAgent
java·开发语言·前端·ai编程
一切皆是因缘际会1 小时前
神经符号融合智能体
大数据·数据结构·人工智能·ai
张忠琳1 小时前
【Go 1.26.4】Golang Slice 深度解析
开发语言·后端·golang
玖玥拾2 小时前
C/C++ 数据结构(四)链表与STL容器
c语言·数据结构·c++·链表·stl库
玖玥拾2 小时前
C/C++ 数据结构(一)基础概念、线性表链表
c语言·数据结构·c++·链表
码云骑士2 小时前
09-Python模块导入机制-sys.path与循环导入的死锁式排查
开发语言·python
星恒随风2 小时前
C++ 模板初阶:从泛型编程、函数模板到类模板,一篇打通基础概念
开发语言·c++·笔记·学习
芋只因2 小时前
力扣100题解(Java版)
数据结构