初出茅庐的小李博客之C语言文件操作

C语言文件操作

在C语言中,文件操作主要是通过标准库函数来实现的。

今天有时间就来学习下一些常用的文件操作函数:

C 语言提供了一个 FILE 数据结构,记录了操作一个文件所需要的信息。该结构定义在头文件stdio.h,所有文件操作函数都要通过这个数据结构,获取文件信息。

struct _iobuf 
{
    char *_ptr;      // 指向缓冲区当前位置的指针
    int _cnt;        // 缓冲区中剩余的字节数
    char *_base;     // 指向缓冲区起始位置的指针
    int _flag;       // 文件状态标志(如错误、文件结束等)
    int _file;       // 文件描述符或句柄
    int _charbuf;    // 用于单字符缓冲
    int _bufsiz;     // 缓冲区大小
    char *_tmpfname; // 临时文件名指针(如果有)
};
typedef struct _iobuf FILE;  // 将结构体重命名为 FILE 类型

什么是文件指针:

开始操作一个文件之前,就要定义一个指向该文件的 FILE 指针,相当于获取一块内存区域,用来保存文件信息。

定义方式:

FILE* fp;

fopen()函数用来打开文件。所有文件操作的第一步,都是使用fopen()打开指定文件。这个函数的原型定义在头文件stdio.h

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

它接受两个参数。第一个参数是文件名(可以包含路径),第二个参数是模式字符串,指定对文件执行的操作,比如下面的例子中,r表示以读取模式打开文件;

第一次运行如果没有这个文件,程序会提示错误。如下所示,所以要想以只读的形式打开这个文件那么这样文件要事先存在。我在桌面手动创建了这个文件。再次试验就可以成果打开。

第一次打开出错:
在这里插入图片描述

第二次打开正常:
在这里插入图片描述

打开文件之后我们试着用fread()来读取文件信息。

fread()函数用于一次性从文件读取较大的数据块,主要用途是将文件内容读入一个数组,适合读取二进制数据。它的原型定义在头文件stdio.h

size_t fread(void* ptr, size_t size,size_t nmemb,FILE* fp);

它接受四个参数

  • ptr:数组地址。
  • size:每个数组成员的大小,单位为字节。
  • nmemb:数组的成员数量。
  • fp:文件指针。

读取字节数可以用一个变量来接收,

// 从文件中读取数据
BytesRead = fread(buffer, sizeof(char), sizeof(buffer) - 1, fp);
printf("读到字节数BytesRead = %d\r\n",BytesRead);

在这里插入图片描述

读取数据时候有可能遇到文件为空的情况,这时候就需要检查是不是文件末尾。检查是否到文件末尾函数是feof

feof 是 C 标准库中的一个函数,用于检查文件是否已到达文件末尾(EOF,End of File)。它通常与文件读写函数(如 freadfgets 等)一起使用,以便在读取文件时检测到文件末尾。

feof 函数原型

int feof(FILE *stream);

参数解释

  • stream:指向 FILE 结构的文件指针。

返回值

  • 如果文件指针已到达文件末尾,则返回非零值 (真)。
  • 否则,返回零 (假)。

如果文本文件里面的内容是空的、那么读取到的数据字节数据应该是0。如图所示。

在这里插入图片描述

现在我试着网文件里写入一些信息。再尝试去读取信息

写入的信息是

This is a test txt.
Hello world!
end

编写读取数据到buffer的代码

    BytesRead = fread(buffer, sizeof(char), sizeof(buffer) - 1, fp);
    printf("读到字节数BytesRead = %d\r\n",BytesRead);
    if (BytesRead == 0)
     {
        if (feof(fp))//文件到达末尾返回非零的真值 
        {
            printf("空文件、到达文件末尾\n");
        }
        else if (ferror(fp))
        {
            perror("没读到数据、读取文件时出错");
        }
        fclose(fp);
        return -1;
    }
    buffer[BytesRead] = '\0';
    printf("文件内容: %s\n", buffer);

读取信息入下所示:

打开文件时正常: No error
读到字节数BytesRead = 36
文件内容:
This is a test txt.
Hello world!
end
--------------------------------
Process exited after 0.04219 seconds with return value 0
请按任意键继续. . .

在这里插入图片描述

fclose 是 C 标准库中的一个函数,用于关闭已经打开的文件。关闭文件可以释放与该文件相关的资源,并确保所有缓冲区中的数据被写入文件。

fclose 函数原型

int fclose(FILE *stream);

参数解释

  • stream:指向 FILE 结构的文件指针,该文件指针指向要关闭的文件。

返回值

  • 如果成功关闭文件,返回0。
  • 如果发生错误,返回 EOF(通常为 -1)

完整的代码如下:

#include <stdio.h>

int main(void)
{
    FILE *fp;         // 定义一个 FILE 类型的指针
    char buffer[256]; // 定义一个缓冲区用于存储读取的数据
    size_t BytesRead; // 定义读取到多少个字节

    // 打开一个文件用于读取
    fp = fopen("example.txt", "r");
    if (fp == NULL)
    {
        perror("打开文件时出错");
        return -1;
    }
    else
    {
        printf("打开文件正常\r\n");
    }

    // 从文件中读取数据
    BytesRead = fread(buffer, sizeof(char), sizeof(buffer) - 1, fp);
    printf("读到字节数 BytesRead = %zu\r\n", BytesRead);

    if (BytesRead == 0)
    {
        if (feof(fp)) // 文件到达末尾返回非零的真值
        {
            printf("空文件或到达文件末尾\r\n");
        }
        else if (ferror(fp))
        {
            perror("没读到数据,读取文件时出错");
        }
        fclose(fp);
        return -1;
    }

    // 为缓冲区添加字符串结束符
    buffer[BytesRead] = '\0';
    printf("文件内容:\r\n%s\r\n", buffer);

    // 关闭文件
    if (fclose(fp) == 0) // fclose 关闭成功返回0,关闭失败返回EOF
    {
        printf("成功关闭文件\r\n");
    }
    else
    {
        perror("关闭文件时出错");
    }

    return 0;
}

补充说明:EOF

C 语言的文件操作函数的设计是,如果遇到文件结尾,就返回一个特殊值。程序接收到这个特殊值,就知道已经到达文件结尾了。

头文件stdio.h为这个特殊值定义了一个宏EOF(end of file 的缩写),它的值一般是-1。这是因为从文件读取的二进制值,不管作为无符号数字解释,还是作为 ASCII 码解释,都不可能是负值,所以可以很安全地返回-1,不会跟文件本身的数据相冲突。

需要注意的是,不像字符串结尾真的存储了\0这个值,EOF并不存储在文件结尾,文件中并不存在这个值,完全是文件操作函数发现到达了文件结尾,而返回这个值。

fopen打开文件模式可能情况

以下是 fopen 函数的所有可能模式及其详细解释,包括注意事项:

模式模式说明文件指针位置文件存在文件不存在读操作写操作注意事项
r读模式文件开始读取文件返回 NULL允许不允许文件必须存在,否则返回 NULL。
w写模式文件开始文件内容被清空创建新文件不允许允许打开时会清空文件内容。
a追加写模式文件末尾文件末尾追加创建新文件不允许允许写操作总是在文件末尾。
r+读写模式文件开始读取和写入返回 NULL允许允许文件必须存在,否则返回 NULL。
w+读写模式文件开始文件内容被清空创建新文件允许允许打开时会清空文件内容。
a+读写模式文件末尾读取和追加创建新文件允许允许写操作总是在文件末尾。

注意事项

  1. r 模式

    • 只读模式,如果文件不存在,返回 NULL。因此在打开文件后,必须检查文件指针是否为 NULL
  2. w 模式

    • 只写模式,打开文件时会清空文件内容。如果文件不存在,则创建新文件。这种模式不允许读取文件内容。
  3. a 模式

    • 追加写模式,文件指针总是指向文件末尾。即使使用 fseek 移动文件指针,写入操作仍会在文件末尾。如果文件不存在,则创建新文件。这种模式不允许读取文件内容。
  4. r+ 模式

    • 读写模式,文件指针指向文件开始,允许读取和写入。如果文件不存在,返回 NULL。因此在打开文件后,必须检查文件指针是否为 NULL
  5. w+ 模式

    • 读写模式,打开文件时会清空文件内容,文件指针指向文件开始。如果文件不存在,则创建新文件。这种模式允许读取和写入,但注意文件内容会被清空。
  6. a+ 模式

    • 读写模式,文件指针指向文件末尾,允许读取和追加。如果文件不存在,则创建新文件。尽管可以读取文件内容,但写操作总是在文件末尾。

示例代码

以下是如何使用这些模式打开文件的示例代码:

#include <stdio.h>

void open_file(const char *filename, const char *mode) 
{
    FILE *fp = fopen(filename, mode);
    if (fp == NULL) 
    {
        perror("打开文件失败");
        return;
    }
    printf("以模式 '%s' 成功打开文件\r\n", mode);
    // 关闭文件
    if (fclose(fp) == 0) // fclose 关闭成功返回0,关闭失败返回EOF
    {
        printf("成功关闭文件\r\n");
    }
    else
    {
        perror("关闭文件时出错");
    }
}

int main(void) 
{
    open_file("example_r.txt", "r");
    open_file("example_w.txt", "w");
    open_file("example_a.txt", "a");
    open_file("example_r+.txt", "r+");
    open_file("example_w+.txt", "w+");
    open_file("example_a+.txt", "a+");
    return 0;
}

上边代码运行后只会产生四个文件

在这里插入图片描述

在这里插入图片描述

有关文件操作的接口还有以下几个,如果大家感兴趣可以点个在看,我继续更新!

fwrite():写入文件

fseek():移动文件指针到指定位置

ftell():获取文件指针当前位置

fgetc():从文件中读取一个字符

fputc():写入一个字符到文件中

fscanf():从文件中读取格式化输入

fprintf():按格式写入到文件中

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何通过IP地址查询地理位置及运营商信息

在数字时代&#xff0c;IP地址&#xff08;Internet Protocol Address&#xff0c;互联网协议地址&#xff09;已经成为我们日常网络活动的重要组成部分。每台连接到互联网的设备都被分配了一个唯一的IP地址&#xff0c;它不仅可以识别设备&#xff0c;还可以揭示设备的地理位置…

python数据分析入门学习笔记

目录 一、 数据分析有关的python库简介 (一)numpy (二)pandas (三)matplotlib (四)scipy (五)statsmodels (六)scikit-learn 二、 数据的导入和导出 三、 数据筛选 四、 数据描述 五、 数据处理 六、 统计分析 七、 可视化 八、 其它![](https://…

【C语言】—— 文件操作(下)

【C语言】—— 文件操作&#xff08;下&#xff09; 前言&#xff1a;五、文件的顺序读写5.1、 顺序读写函数介绍5.2、 f p u t c fputc fputc 函数5.3、 f g e t c fgetc fgetc 函数5.4、 f p u t s fputs fputs 函数5.5、 f g e t s fgets fgets 函数5.6、 f p r i n t f…

html+css+js淘宝商品界面

点击商品&#xff0c;alert弹出商品ID 图片使用了占位符图片&#xff0c;加载可能会慢一点 你可以把它换成自己的图片&#x1f603;源代码在图片后面 效果图 源代码 <!DOCTYPE html> <html lang"zh"> <head> <meta charset"UTF-8"…

Word “当前页“ 与 “前一页“ (含部分内容)间有大半页空白,删除空白方法

鼠标光标选中需要向上移的句子&#xff0c;右键点击“段落”&#xff0c;然后在跳出的窗口中按照“换行和分页”中的红色方框内取消勾选后&#xff0c;点击确定即可。

金斗云 HKMP智慧商业软件 任意用户创建漏洞复现

0x01 产品简介 金斗云智慧商业软件是一款功能强大、易于使用的智慧管理系统,通过智能化的管理工具,帮助企业实现高效经营、优化流程、降低成本,并提升客户体验。无论是珠宝门店、4S店还是其他零售、服务行业,金斗云都能提供量身定制的解决方案,助力企业实现数字化转型和智…

Proteus-51单片机-DS18B20多点测温

DS18B20多点测温 一、Proteus仿真演示 每个DS18B20都有一个唯一的64位序列号,这使得在同一总线上可以挂载多个传感器,无需额外的地址分配。主机(通常为单片机)通过特定的时序控制,可以依次读取各个DS18B20的温度数据,实现分布式测温。 二、代码特点 三、开发环境介绍 本…

【unity实战】使用unity的新输入系统InputSystem+有限状态机设计一个玩家状态机控制——实现玩家的待机 移动 闪避 连击 受击 死亡状态切换

最终效果 文章目录 最终效果前言人物素材新输入系统InputSystem的配置动画配置代码文件路径状态机脚本创建玩家不同的状态脚本玩家控制源码完结 前言 前面我们已经写过了使用有限状态机制作一个敌人AI&#xff1a;【unity实战】在Unity中使用有限状态机制作一个敌人AI 那么玩…

收银系统源码分享-PHP可二开

千呼新零售2.0系统是零售行业连锁店一体化收银系统&#xff0c;包括线下收银线上商城连锁店管理ERP管理商品管理供应商管理会员营销等功能为一体&#xff0c;线上线下数据全部打通。 适用于商超、便利店、水果、生鲜、母婴、服装、零食、百货、宠物等连锁店使用。 私有化独立…

面向对象-封装

一.包 1.简介 当我们把所有的java类都写src下的第一层级&#xff0c;如果是项目中&#xff0c;也许会有几百个java文件。 src下的文件会很多&#xff0c;开发的时候不方便查找&#xff0c;也不方便维护如果较多的文件中有同名的&#xff0c;十分麻烦 模块1中有一个叫test.ja…

Nuxtjs3教程

起步 官方文档 官方目录结构 安装 npx nuxi@latest init <project-name>后面跟着提示走就行 最后yarn run dev 启动项目访问localhost:3000即可 路由组件 app.vue为项目根组件 <nuxt-page />为路由显示入口 将app.vue更改内容如下 <template><d…

WPS中制作甘特图的详细教程

网上没几个详细说怎么在WPS中制作甘特图的&#xff0c;我自己整理了一下详细教程&#xff0c;最终效果如下图所示&#xff1a; 1.写好需要展示的项目相关信息&#xff0c;如下图所示&#xff1a; #####这个进度的百分比渐变效果这样设置就行了 2.现在我们需要计算已用时间和剩…

lodash中flush的使用(debounce、throttle)

在项目的配置中&#xff0c;看到了一个请求&#xff0c;类似是这样的 import { throttle } from lodash-es// 请求函数 async function someFetch(){const {data} await xxx.post()return data }// 节流函数 async function throttleFn(someFetch,1000)// 执行拿到数据函数 a…

Zabbix 配置MySQL数据库监控

Zabbix MySQL数据库监控简介 通过 Zabbix 监控 MySQL 数据库&#xff0c;可以获取有关数据库性能、运行状况和资源使用情况的详细信息&#xff0c;帮助及时发现和解决问题。 Zabbix官方提供了一个名为MySQL by Zabbix agent的监控模板&#xff0c;该模板专为 Zabbix 通过 Zabb…

Java中的文件IO

文件,我们之前在C语言中接触过,是在硬盘上存储数据的方式,操作系统帮我们把硬盘的一些细节都封装起来了,因此在这里我们只需要了解文件的相关接口即可. 首先硬盘是用来存储数据的,和内存相比,硬盘的存储空间更大,访问速度更慢,成本更低,可以实现持久化存储,而操作系统通过&quo…

Polkadot 安全机制揭秘:保障多链生态的互操作性与安全性

作者&#xff1a;Filippo Franchini&#xff0c;Web3 Foundation 原文&#xff1a;https://x.com/filippoweb3/status/1806318265536242146 编译&#xff1a;OneBlock Polkadot 是一个创新的多链区块链平台&#xff0c;旨在实现不同区块链之间的互操作性和共享安全性。本文将详…

c++习题02-浮点数求余

目录 一&#xff0c;问题 二&#xff0c;思路 三&#xff0c;代码 一&#xff0c;问题 二&#xff0c;思路 虽然在浮点类型中没有取余的运算&#xff08;无法直接使用%符号取余&#xff09;&#xff0c;但是我们都知道在数学中&#xff0c;除法是减法的连续运算&#xff…

软件测试最全面试题及答案整理(2024最新版)

1、你的测试职业发展是什么? 测试经验越多&#xff0c;测试能力越高。所以我的职业发展是需要时间积累的&#xff0c;一步步向着高级测试工程师奔去。而且我也有初步的职业规划&#xff0c;前3年积累测试经验&#xff0c;按如何做好测试工程师的要点去要求自己&#xff0c;不断…

师从IEEE fellow|博士后加拿大阿尔伯塔大学成行

V老师指定申请加拿大&#xff0c;优先对方出资的博士后&#xff0c;如果外方无资助&#xff0c;也可以自筹经费&#xff0c;但要求必须是博士后头衔。最终我们为其落实了加拿大阿尔伯塔大学的postdoctoral fellow&#xff08;博士后研究员&#xff09;&#xff0c;尽管是无薪职…

经典链表算法题:找到环的入口。清晰图示推导出来

Leetcode题目链接 原理 重画链表如下所示&#xff0c;线上有若干个节点。记蓝色慢指针为 slow&#xff0c;红色快指针为 fast。初始时 slow 和 fast 均在头节点处。 使 slow 和 fast 同时前进&#xff0c;fast 的速度是 slow 的两倍。当 slow 抵达环的入口处时&#xff0c;如…