【C语言文件操作详解】fopen 函数全解析 —— 模式参数、使用技巧与重定向的区别

在 C 语言中,文件的读写是一个非常常见的需求。fopen 是标准库中提供的函数,用来打开文件,返回一个文件指针供后续操作使用。本篇博客将详细介绍 fopen 的使用方法、每个参数的含义,以及它与 Shell 中 >、>> 重定向符的联系与区别。

一、fopen 函数原型

FILE *fopen(const char *filename, const char *mode);
  • filename:要打开的文件路径,可以是相对路径或绝对路径。
  • mode:打开文件的方式,也叫“模式”,是一个字符串,控制你要如何访问文件(读、写、追加等)。

返回值是一个 FILE * 类型的文件指针,如果打开失败则返回 NULL。

二、mode 模式参数详解

模式描述文件是否需要存在?是否会清空原文件?
"r"只读模式打开文本文件
"w"只写模式打开文本文件是(若存在则清空)
"a"追加写入模式打开文本文件否(写入时追加)
"r+"读写模式打开文本文件
"w+"读写模式,若文件存在则清空
"a+"读写模式,从文件末尾追加写入
"rb"以二进制只读方式打开文件
"wb"以二进制只写方式打开文件
"ab"以二进制追加方式打开文件

2.1 “r”:只读模式

只能读取已有文件,文件必须存在。

#include <stdio.h>int main() {FILE *fp = fopen("data.txt", "r");if (!fp) {perror("无法打开文件");return 1;}char buffer[100];while (fgets(buffer, sizeof(buffer), fp)) {printf("%s", buffer);}fclose(fp);return 0;
}

在终端将显示data.txt中原有的文件内容

2.2 “w” 只写模式

fopen(“log.txt”, “w”) 以“写模式”(“w”)打开 log.txt 文件。如果文件不存在,它会被创建。如果文件已经存在,文件的原始内容会被清空,重新写入新内容。
fprintf(fp, “Hello, world!\n”); 这一行会将字符串 “Hello, world!\n” 写入 log.txt 文件中。
执行完后,文件会关闭,原文件中的所有内容(包括原先的 “hello”)都会被新内容覆盖。
假设log.txt中的内容为:

hello

那么执行下面的代码之后:

#include <stdio.h>int main() {FILE *fp = fopen("log.txt", "w");if (!fp) {perror("无法打开文件");return 1;}fprintf(fp, "Hello, world!\n");fclose(fp);return 0;
}

因此,假设文件 log.txt 在之前包含 “hello”,再次运行此程序后,文件的内容会被重写为:

Hello, world!

2.3 “a”:追加模式

fopen(“log.txt”, “a”) 以“追加模式”(“a”)打开文件。如果 log.txt 文件不存在,它会被创建。如果文件已经存在,新写入的内容会被添加到文件的末尾,而不会覆盖原有的内容。
fprintf(fp, “程序执行了一次。\n”); 这一行会把字符串 “程序执行了一次。\n” 写入文件。
执行完后,文件会关闭。
假设文件 log.txt 中原本的内容为:

hello

那么执行下面的代码之后:

#include <stdio.h>int main() {FILE *fp = fopen("log.txt", "a");if (!fp) {perror("无法打开文件");return 1;}fprintf(fp, "程序执行了一次。\n");fclose(fp);return 0;
}

每次执行该程序时,程序都会在文件末尾追加一行 “程序执行了一次。\n”,所以第一次执行后的文件内容会变为:

hello
程序执行了一次。

如果再次运行该程序,文件内容会变为:

hello
程序执行了一次。
程序执行了一次。

每次执行程序,都会在文件末尾追加 “程序执行了一次。\n” 这一行,而不会覆盖原有的内容。

2.4 “r+”:读写模式

fopen(“log.txt”, “r+”) 以“读写模式”(“r+”)打开文件。这种模式要求文件必须已经存在。如果文件不存在,程序会输出 无法打开文件 并退出。
fprintf(fp, “MODIFIED”); 会将字符串 “MODIFIED” 写入文件,从文件的开头开始覆盖原有的内容。由于 “MODIFIED” 的长度是 8 个字符,它会覆盖文件中的前 8 个字节。
假设原文件log.txt 的内容是:

hello

执行下面代码:

#include <stdio.h>int main() {FILE *fp = fopen("log.txt", "r+");if (!fp) {perror("无法打开文件");return 1;}// 覆盖文件前几个字节fprintf(fp, "MODIFIED");fclose(fp);return 0;
}

执行 fprintf(fp, “MODIFIED”);,文件的前 8 个字节会被 “MODIFIED” 替换。由于 “MODIFIED” 比原来的 hello 长,因此文件会变成:

MODIFIED

2.5. “w+”:读写模式

fopen(“log.txt”, “w+”) 以“读写模式”(“w+”)打开文件。如果文件不存在,它会被创建。如果文件已经存在,它会被清空(即文件内容会被删除),然后可以进行读写操作。
fprintf(fp, “Writing then reading.\n”); 这一行将字符串 “Writing then reading.\n” 写入 log.txt 文件。
rewind(fp); 将文件指针移动回文件的开头,为后续的读取操作做准备。
fgets(buffer, sizeof(buffer), fp); 读取文件内容并将其存储在 buffer 数组中,直到遇到换行符或文件末尾。这里会读取写入的内容 “Writing then reading.\n”。
printf(“读取内容: %s”, buffer); 打印读取到的内容。

#include <stdio.h>int main() {FILE *fp = fopen("log.txt", "w+");if (!fp) {perror("无法打开文件");return 1;}fprintf(fp, "Writing then reading.\n");rewind(fp); // 返回文件开头char buffer[100];fgets(buffer, sizeof(buffer), fp);printf("读取内容: %s", buffer);fclose(fp);return 0;
}

控制台会输出:

读取内容: Writing then reading.

文件 log.txt 的内容会变为:

Writing then reading.

2.6 “a+”:读写追加模式

log.txt 文件的内容将被 追加 新数据,同时程序会读取并打印文件的全部内容。
fopen(“log.txt”, “a+”);

  • 打开文件 log.txt,模式为 “a+”,表示 读写追加模式。
  • 如果文件不存在,它会被创建;如果文件存在,原有内容 不会被清空,且新的写入内容会追加到文件末尾。
  • 该模式允许读取和写入操作,但是写入内容总是从文件末尾开始,不会覆盖原有数据。

fprintf(fp, “添加一行数据\n”);

  • 向文件追加一行数据 “添加一行数据\n”。由于是 “a+” 模式,文件指针会自动移到文件末尾,新的内容会添加到文件的末尾。

rewind(fp);

  • 将文件指针重置到文件开头。这样做的目的是为了能够从文件的开始位置读取内容。

while (fgets(buffer, sizeof(buffer), fp))

  • 使用 fgets 逐行读取文件内容,并将读取的每行内容打印出来。由于文件指针已被 rewind()
    移动到文件开头,这个循环将从文件的第一行开始读取并输出。

假设文件 log.txt 原始内容是:

hello

执行下面代码后:

#include <stdio.h>int main() {FILE *fp = fopen("log.txt", "a+");if (!fp) {perror("无法打开文件");return 1;}fprintf(fp, "添加一行数据\n");rewind(fp);  // 读取需要重置到文件开头char buffer[100];while (fgets(buffer, sizeof(buffer), fp)) {printf("%s", buffer);}fclose(fp);return 0;
}

文件内容变为:

hello
添加一行数据

程序会打印:

hello
添加一行数据

三、fopen 与 Shell 重定向 >、>> 的关系与区别

Shell 中的重定向:
1.>:输出重定向,若文件存在则清空,等价于 fopen(“file.txt”, “w”)。
2.>>:追加输出,文件存在时追加到末尾,等价于 fopen(“file.txt”, “a”)。

对比总结:

操作Shell 表达方式C 语言等价 fopen 模式
重定向输出到文件(覆盖)command > file.txt"w"
追加输出到文件command >> file.txt"a"

示例:

echo "日志内容" > log.txt   # 覆盖写入
echo "更多日志" >> log.txt  # 追加写入

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/905067.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

青少年编程与数学 02-019 Rust 编程基础 02课题、开始编程

青少年编程与数学 02-019 Rust 编程基础 02课题、开始编程 一、游戏规则二、实现步骤1. 创建项目2. 编写代码3. 添加依赖4. 运行程序 三、代码解析四、println! 的用法基本用法使用占位符示例控制输出宽度和精度示例 输出多个变量示例 注意事项小结 五、管理多个项目1. 创建 Wo…

拒绝flash插件打劫!如何在vscode上玩4399小游戏

现在电脑上玩4399都需要flash插件了 这也导致了很多人无法玩到小时候的游戏 今天介绍一款插件 功能强大 即安即玩 首先打开vscode 点开小方框&#xff08;拓展&#xff09;搜索4399 认准4399 on vscode点击安装 安装完毕后 按下 Ctrl Shift P , 输入 4399 on VSCode 或…

RHCSA Linux系统 Web页面 论坛 网盘的搭建

Web 服务搭建 [rootlocalhost ~]#yum install httpd -y [rootlocalhost ~]#cd /var/www/htm1/ [rootalocalhost html]#echo 江停严峫 >index.html [rootlocalhost html]#setenforce 0 #将 SELinux 模式设置为宽容模式&#xff0c;不强制执行安全策略 [rootlocalhost h…

力扣刷题——二分查找总结

我们可以总结出二分查找的通用做法和常见变种。二分查找是一种在有序数组中高效查找元素的算法&#xff0c;时间复杂度为 O (log n)。 二分查找的通用模板 二分查找的核心思想是将搜索范围不断缩小一半&#xff0c;直到找到目标元素或确定其不存在。以下是通用模板&#xff1…

开源数字人框架 AWESOME-DIGITAL-HUMAN 技术解析与应用指南

一、项目概述 AWESOME-DIGITAL-HUMAN 是一个基于 Live2D 技术的开源数字人框架&#xff0c;它集成了语音识别&#xff08;ASR&#xff09;、大语言模型&#xff08;LLM&#xff09;、语音合成&#xff08;TTS&#xff09;和 Agent 模块化扩展能力&#xff0c;支持快速部署和自…

互联网大厂Java求职面试:基于RAG的智能问答系统设计与实现-2

互联网大厂Java求职面试&#xff1a;基于RAG的智能问答系统设计与实现-2 面试背景 郑薪苦是一名Java开发者&#xff0c;拥有丰富的项目经验&#xff0c;但在面试中总喜欢用奇葩比喻解释技术问题。今天他面对的是某大厂技术总监张总&#xff0c;面试主题为“基于RAG的智能问答…

(二)Linux下基本指令 2

【知识预告】 16. date 指令 17. cal 指令 18. find 指令 19. which指令 20. whereis 指令 21. alias 指令 22. grep 指令 23. zip/unzip 指令 24. tar 指令 25. bc 指令 26. uname ‒r 指令 27. 重要的⼏个热键 28. 关机 16 date 指令 指定格式显⽰时间&#xff1a;date %Y-…

命令行解释器中shell、bash和zsh的区别

命令行解释器&#xff08;Command Line Interpreter&#xff09;是一个程序&#xff0c;它的主要作用是接收用户输入的命令&#xff0c;并执行相应的操作。它充当了用户与操作系统内核之间的桥梁。 一、什么是 Shell&#xff1f; Shell 是一个通用术语&#xff0c;指的是 命令…

二、transformers基础组件之Tokenizer

在使用神经网络处理自然语言处理任务时&#xff0c;我们首先需要对数据进行预处理&#xff0c;将数据从字符串转换为神经网络可以接受的格式&#xff0c;一般会分为如下几步: - Step1 分词:使用分词器对文本数据进行分词(字、字词);- Step2 构建词典:根据数据集分词的结果,构建…

镜像和容器的管理

一、镜像的管理 获取镜像并生成相关容器 # 拉取镜像 docker pull alpine # 默认是latest&#xff0c;也就是最新版本&#xff0c;也可指定版本&#xff08;在镜像名后边加“:版本号”&#xff09; # 或者 # 从主机中导入镜像到docker中 docker image load -i /test#生成容器 …

设计模式简述(十九)桥梁模式

桥梁模式 描述基本组件使用 描述 桥梁模式是一种相对简单的模式&#xff0c;通常以组合替代继承的方式实现。 从设计原则来讲&#xff0c;可以说是单一职责的一种体现。 将原本在一个类中的功能&#xff0c;按更细的粒度拆分到不同的类中&#xff0c;然后各自独立发展。 基本…

ImportError: DLL load failed: 找不到指定的程序。

查看其他博客说是缺少libssl-1_1-x64.dll 和 libcrypto-1_1-x64.dll 然后去下载放到博客说的目录下 没有用 解决不了一点 OpenSSL for Windows 64位 完整安装包 在这里 项目地址: https://gitcode.com/open-source-toolkit/eb627 注意事项 此安装包仅适用于64位Windows系…

电池单元和电极性能

电芯设计中的挑战 对于电池制造商来说&#xff0c;提高电池能量和功率密度至关重要。在高功率密度和长循环寿命之间取得平衡是电池设计中的关键挑战&#xff0c;通常需要仔细优化材料、电极结构和热管理系统。另一个关键挑战是通过优化重量体积比来降低电池单元的总体成本。 工…

数据加密与隐私保护:让你的信息固若金汤

数据加密与隐私保护:让你的信息固若金汤 大家好,我是 Echo_Wish,今天聊聊一个 人人都关心、但很多人没做好 的话题——数据加密与隐私保护的最佳实践。 为什么要重视数据安全? 现在是数字化时代,从个人照片、银行卡信息到企业机密,数据泄露的风险无处不在。你可能觉得自…

【高数上册笔记篇02】:数列与函数极限

【参考资料】 同济大学《高等数学》教材樊顺厚老师B站《高等数学精讲》系列课程 &#xff08;注&#xff1a;本笔记为个人数学复习资料&#xff0c;旨在通过系统化整理替代厚重教材&#xff0c;便于随时查阅与巩固知识要点&#xff09; 仅用于个人数学复习&#xff0c;因为课…

C++(8):类型限定符

目录 1. const&#xff1a;定义常量 2. volatile&#xff1a;易变性修饰 3. restrict&#xff08;C非标准&#xff09; 4. mutable&#xff1a;突破常量性 5. static&#xff1a;静态存储 6. register&#xff08;已弃用&#xff09; 分类修正说明 1. const&#xff1a;…

Nginx yum 安装

一、环境准备 一台装有 CentOS 7.9 的虚拟机 二、安装 安装 yum install -y nginx -y&#xff1a;所有的安装选项都选择 yes。 启动 nginx systemctl enable nginx --now enable&#xff1a;设置 nginx 为开机启动。--now&#xff1a;马上启动 nginx。 查看 nginx 服务状态…

【5分钟学Docker】Docker快速使用

目录 1. 概述 2. 基本操作 2.1. 镜像操作 2.2. 容器操作 2.3. 运行操作 2.4. 镜像保存 2.5. 镜像分享 3. 高级操作 4. 挂载 4.1. 目录挂载 4.2. 卷映射 1. 概述 Docker 镜像有镜像名称和TAG 2. 基本操作 2.1. 镜像操作 查看镜像 docker images docker image ls …

5000字总结 HTML5 中的音频和视频,关羽标签、属性、API 和最佳实践

HTML5 音频与视频开发完全指南&#xff1a;标签、属性、API 与最佳实践 一、引言&#xff1a;HTML5 媒体时代的到来 在 HTML5 之前&#xff0c;网页中的音频和视频播放依赖 Flash、Silverlight 等第三方插件&#xff0c;存在兼容性差、性能瓶颈和安全隐患。HTML5 引入的 <…

【C语言】(9)—指针3

文章目录 一、字符指针的深入理解二、数组指针详解三、二维数组传参的本质四、函数指针及其应用五、函数指针数组与转移表 一、字符指针的深入理解 1.1 字符指针的基本使用 字符指针(char*)是指向字符类型数据的指针&#xff0c;它有两种常见的使用方式&#xff1a; // 方式一…