文件操作(随机读写篇)

news2025/1/22 15:05:45

1. 铺垫

建议先看:

文件操作(基础知识篇)-CSDN博客

文件操作(顺序读写篇)-CSDN博客

首先要指出的是,本篇文章中的“文件指针”并不是指FILE*类型的指针,而是类似于打字时的光标的东西。

打开文件时候,文件指针会指向文件开头。

刚打开文本文件时,文件指针自动指向文件起始处,之后会随读写内容移动。

读数据时,从文件指针位置向后读取,读取成功后,文件指针指向被读取数据的末尾;写数据时,从文件指针位置向后写,写入成功后,文件指针指向被写入数据的的末尾。

当我们想要在某指定位置处读取数据,或着在某指定位置处写入数据时,就需要用到接下来所要介绍的函数,也就是进行文件的随机读写。

2. fseek函数

该函数可以设置文件指针的位置。

通过三个标准位置以及相对于标准位置的偏移量来指定文件指针的位置。

第二个参数表示相对于标准位置的偏移量,正数表示向后偏移,负数表示向前偏移。

第三个参数表示标准位置,其可取的值有三个:

SEEK_SET文件开头
SEEK_CUR文件指针当前位置
SEEK_END文件末尾

成功设置文件指针的位置时,返回0;失败时(发生错误),返回非零的值。

使用示例:

#include <stdio.h>

int main ()
{
    FILE * pFile;
    pFile = fopen ( "example.txt" , "wb" );
    fputs ( "This is an apple." , pFile );
    fseek ( pFile , 9 , SEEK_SET );
    fputs ( " sam" , pFile );
    fclose ( pFile );

    return 0;
}

3. ftell

该函数可以获取当前文件指针相对于起始位置的偏移量。

获取成功时,返回文件指针相对于起始位置的偏移量;获取失败时,返回-1L。

使用示例:

#include <stdio.h>
int main ()
{
    FILE * pFile;
    long size;
    pFile = fopen ("myfile.txt","rb");
    if (pFile==NULL) 
    perror ("Error opening file");
    else
    {
        fseek (pFile, 0, SEEK_END); // non-portable
        size=ftell (pFile);
        fclose (pFile);
        printf ("Size of myfile.txt: %ld bytes.\n",size);
    }

    return 0;
}

4. rewind

该函数可以使文件指针回到文件起始位置。

使用示例: 

#include <stdio.h>
int main ()
{
    int n;
    FILE * pFile;
    char buffer [27];
 
    pFile = fopen ("myfile.txt","w+");
    for ( n='A' ; n<='Z' ; n++)
    fputc ( n, pFile);
    rewind (pFile);
 
    fread (buffer,1,26,pFile);
    fclose (pFile);
 
    buffer[26]='\0';
    printf(buffer);

    return 0;
}

5. 文件读取结束的判定

被错误使用的feof函数

牢记:在文件读取过程中,不能用feof函数的返回值直接来判断文件的是否结束。

feof 的作用是:当文件读取结束的时候,判断是读取结束的原因是否是“遇到文件尾结束”。

1. 文本文件读取是否结束,判断返回值是否为 EOF ( fgetc ),或者 NULL ( fgets )

例如:

• fgetc 判断是否为 EOF。

• fgets 判断返回值是否为 NULL。

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
    int c; // 注意:int,⾮char,要求处理EOF
    FILE* fp = fopen("test.txt", "r");
    if(!fp) 
    {
        perror("File opening failed");
        return EXIT_FAILURE;
    }
    //fgetc 当读取失败的时候或者遇到⽂件结束的时候,都会返回EOF
    while ((c = fgetc(fp)) != EOF) // 标准C I/O读取⽂件循环
    { 
        putchar(c);
    }
    //判断是什么原因结束的
    if (ferror(fp))
    puts("I/O error when reading");
    else if (feof(fp))
    puts("End of file reached successfully");
    fclose(fp);

    return 0;
}

 2. 二进制文件的读取结束判断,判断返回值是否小于实际要读的个数。

例如:

• fread判断返回值是否小于实际要读的个数。

#include <stdio.h>
enum { SIZE = 5 };
int main(void)
{
    double a[SIZE] = {1.,2.,3.,4.,5.};
    FILE *fp = fopen("test.bin", "wb"); // 必须⽤⼆进制模式
    fwrite(a, sizeof *a, SIZE, fp); // 写 double 的数组
    fclose(fp);

    double b[SIZE];
    fp = fopen("test.bin","rb");
    size_t ret_code = fread(b, sizeof *b, SIZE, fp); // 读 double 的数组
    if(ret_code == SIZE) 
    {
        puts("Array read successfully, contents: ");
        for(int n = 0; n < SIZE; ++n) 
        printf("%f ", b[n]);
        putchar('\n');
    } 
    else 
    { // error handling
        if (feof(fp))
        printf("Error reading test.bin: unexpected end of file\n");
        else if (ferror(fp)) 
        {
            perror("Error reading test.bin");
        }
    }
    fclose(fp);

    return 0;
}

6. 文件缓冲区

ANSIC 标准采用“缓冲文件系统” 处理的数据文件的,所谓缓冲文件系统是指系统自动地在内存中为程序中每一个正在使用的文件开辟⼀块“文件缓冲区”。从内存向磁盘输出数据会先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘上。如果从磁盘向计算机读入数据,则从磁盘文件中读取数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。

缓冲区的大小是根据C编译系统决定的。

缓冲区的存在,是为了避免程序频繁地向操作系统发出申请,从而影响其他进程。

#include <stdio.h>
#include <windows.h>
//VS2019 WIN11环境测试

int main()
{
    FILE*pf = fopen("test.txt", "w");
    fputs("abcdef", pf);//先将代码放在输出缓冲区
    printf("睡眠10秒-已经写数据了,打开test.txt⽂件,发现⽂件没有内容\n");
    Sleep(10000);
    printf("刷新缓冲区\n");
    fflush(pf);//刷新缓冲区时,才将输出缓冲区的数据写到⽂件(磁盘)
    //注:fflush 在⾼版本的VS上不能使⽤了
    printf("再睡眠10秒-此时,再次打开test.txt⽂件,⽂件有内容了\n");
    Sleep(10000);
    fclose(pf);
    //注:fclose在关闭⽂件的时候,也会刷新缓冲区
    pf = NULL;

    return 0;
}

这里可以得出一个结论: 因为有缓冲区的存在,C语言在操作文件的时候,需要做刷新缓冲区或者在文件操作结束的时候关闭文件。

如果不做,可能导致读写文件的问题。

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

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

相关文章

EMD关于信号的重建,心率提取

关于EMD的俩个假设&#xff1a; IMF 有两个假设条件&#xff1a; 在整个数据段内&#xff0c;极值点的个数和过零点的个数必须相等或相差最多不能超过一 个&#xff1b;在任意时刻&#xff0c;由局部极大值点形成的上包络线和由局部极小值点形成的下包络线 的平均值为零&#x…

WebGIS开发

1.准备工作 高德开发API注册账号&#xff0c;创建项目拿到key和密钥 高德key 2.通过JS API引入高德API <html><head><meta charset"utf-8" /><meta http-equiv"X-UA-Compatible" content"IEedge" /><metaname&quo…

Ubuntu上安装d4rl数据集

Ubuntu上安装d4rl数据集 D4RL的官方 github: https://github.com/Farama-Foundation/D4RL 一、安装Mujoco 1.1 官网下载mujoco210文件 如果装过可以跳过这步 链接&#xff1a;https://github.com/deepmind/mujoco/releases/tag/2.1.0 下载第一个文件即可。我这里是在windo…

【JAVA】精密逻辑控制过程(分支和循环语句)

✅作者简介&#xff1a;大家好&#xff0c;我是橘橙黄又青&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a; 橘橙黄又青-CSDN博客 目标&#xff1a; 1. Java 中程序的逻辑控制语句 2. Java 中的输入输出方式 3. 完成…

动手学机器学习线性回归+习题

线性回归 矩阵求导&#xff1a; 左边是分子布局&#xff0c;右边是分母布局&#xff0c;一般都用分母布局 解析解与数值解&#xff1a; 解析解是严格按照公式逻辑推导得到的&#xff0c;具有基本的函数形式。给出任意的自变量就可以求出其因变量 数值解是采用某种计算方法&a…

写作类AI推荐(二)

本章要介绍的写作AI如下&#xff1a; 火山写作 主要功能&#xff1a; AI智能创作&#xff1a;告诉 AI 你想写什么&#xff0c;立即生成你理想中的文章AI智能改写&#xff1a;选中段落句子&#xff0c;可提升表达、修改语气、扩写、总结、缩写等文章内容优化&#xff1a;根据全文…

黑马鸿蒙笔记2

1.图片设置&#xff1a; 1 加载网络图片&#xff0c;申请权限。 申请权限&#xff1a;entry - src - resources - module.json5 2 加载本地图片 ,两种加载方式 API 鼠标悬停在Image&#xff0c; 点击show in API Reference interpolation&#xff1a;看起来更加清晰 resou…

【C++】string类(常用接口)

&#x1f308;个人主页&#xff1a;秦jh__https://blog.csdn.net/qinjh_?spm1010.2135.3001.5343&#x1f525; 系列专栏&#xff1a;http://t.csdnimg.cn/eCa5z 目录 修改操作 push_back append operator assign insert erase replace c_str find string类非成…

【ReadPapers】A Survey of Large Language Models

LLM-Survey的llm能力和评估部分内容学习笔记——思维导图 思维导图 参考资料 A Survey of Large Language Models论文的github仓库

【AcWing】蓝桥杯集训每日一题Day8|日期问题|前缀和|3498.日期差值(C++)

3498.日期差值 3498. 日期差值 - AcWing题库难度&#xff1a;简单时/空限制&#xff1a;1s / 64MB总通过数&#xff1a;5763总尝试数&#xff1a;18345来源&#xff1a;上海交通大学考研机试题算法标签模拟日期问题 题目内容 有两个日期&#xff0c;求两个日期之间的天数&…

ESD保护二极管ESD9B3.3ST5G 以更小的空间实现强大的保护 车规级TVS二极管更给力

什么是汽车级TVS二极管&#xff1f; TVS二极管是一种用于保护电子电路的电子元件。它主要用于电路中的过电压保护&#xff0c;防止电压过高而损坏其他部件。TVS二极管通常被称为“汽车级”是因为它们能够满足汽车电子系统的特殊要求。 在汽车电子系统中&#xff0c;由于车辆启…

22 多态

目录 多态的概念多态的定义及实现抽象类多态的原理单继承和多继承关系中的虚函数表继承和多态常见的面试问题 前言 需要声明的&#xff0c;下面的代码和解释的哦朴实vs2013x86环境&#xff0c;涉及指针是4bytes&#xff0c;如果要其他平台下&#xff0c;部分代码需要改动。比…

vue源码解析—— watch/computed的实现逻辑和区别

watch 和 computed 是 Vue 中的两个重要的响应式属性&#xff0c;它们在实现机制和使用上存在一些区别。 watch&#xff1a;用于监听数据的变化&#xff0c;并在数据变化时执行回调函数。可以使用 deep 配置项来开启深度监听&#xff0c;监听数据的子属性变化。可以使用 immedi…

安装 kubesphere 插件报错Error: UPGRADE FAILED: \“ks-minio\“ has no deployed releases

安装 kubesphere 插件报错Error: UPGRADE FAILED: “ks-minio” has no deployed releases TASK [common : Kubesphere | Creating manifests] ******************************** ok: [localhost] > (item{uname: ucustom-values-minio, ufile: ucustom-values-minio.yaml}…

Linux shell编程学习笔记43:cut命令

0 前言 在 Linux shell编程学习笔记42&#xff1a;md5sum 中&#xff0c;md5sum命令计算md5校验值后返回信息的格式是&#xff1a; md5校验值 文件名 包括两项内容&#xff0c;前一项是md5校验值 &#xff0c;后一项是文件名。 如果我们只想要前面的md5 校验值&#xff0c…

完整部署一套k8s-v.1.28.0版本的集群

一、系统情况 虚拟机版本&#xff1a;esxi 6.7 系统版本&#xff1a;centos7.9_2009_x86 配置&#xff1a;4核8G&#xff08;官网最低要求2核2G&#xff09; 192.168.0.137 master节点 192.168.0.139 node2节点 192.168.0.138 node1节点&#xff08;节点扩容练习&#xf…

拥抱挑战,开启增长:2024年全球产品团队的OKR策略

2024年&#xff0c;全球经济格局进入重塑阶段。消费者在消费选择上趋于严苛&#xff0c;企业需推出更具吸引力的产品与服务&#xff0c;以赢得消费者的青睐。同时&#xff0c;企业需通过持续创新&#xff0c;提升产品竞争力&#xff0c;方能在充满挑战的市场环境中实现持续增长…

Kaggle注册验证码问题(Captcha must be filled out.)

Kaggle注册验证码问题 Captcha must be filled out.使用Edge浏览器 Header Editor 插件安装 下载插件Header Editor 导入重定向脚本 点击扩展插件&#xff0c; 打开Header Editor插件&#xff0c;进行管理 点击导入输入下载链接进行下载或者导入本地json文件(二者任选其一…

文件操作(顺序读写篇)

1. 顺序读写函数一览 函数名功能适用于fgetc字符输入函数所有输入流fputc字符输出函数所有输出流fgets文本行输入函数所有输入流fputs文本行输出函数所有输出流fscanf格式化输入函数所有输入流fprintf格式化输出函数所有输出流fread二进制输入文件fwrite二进制输出文件 上面说…

代码学习记录31---动态规划开始

随想录日记part31 t i m e &#xff1a; time&#xff1a; time&#xff1a; 2024.03.29 主要内容&#xff1a;今天开始要学习动态规划的相关知识了&#xff0c;今天的内容主要涉及四个方面&#xff1a; 理论基础 ; 斐波那契数 ;爬楼梯 ;使用最小花费爬楼梯。 理论基础 509. 斐…