当前位置: 首页 > news >正文

【C语言入门级教学】⽂件的随机读写和文件缓冲区

文章目录

  • **点击这里查看文件相关知识的第一篇**(这是第三篇)
  • **点击这里查看文件相关知识第二篇**
    • 5.11 对⽐几组函数
      • 5.11.1 sprintf
      • 5.11.2 sscanf
    • 5.12总结
  • 6.⽂件的随机读写
    • 6.1 fseek
    • 6.2 ftell
    • 6.3 rewind
  • 7.⽂件读取结束的判定
    • 7.1 被错误使⽤的 feof
  • 8.⽂件缓冲区
    • 8.1 fflush
  • 9.更新文件

点击这里查看文件相关知识的第一篇(这是第三篇)

点击这里查看文件相关知识第二篇

5.11 对⽐几组函数

5.11.1 sprintf

int sprintf(char* str,const char* format,...);
//对比
int printf(const char* format,...);
//将格式化数据打印到屏幕(标准输出)上

功能

将格式化数据写入字符数组(字符串)。它类似于printf,但输出目标不是控制台或文件,而是用户指定的内存缓冲区。常用于动态生成字符串、拼接数据或转换数据格式。简而言之就是将格式化的数据转换成一个字符串

参数

str:指向字符数组的指针,用于存储生成的字符串(需确保足够大以防溢出)

format:格式化字符串,定义输出格式(如%d、%f、%s等)

…:可变参数列表,提供与格式字符串中说明符对应的数据

返回值

成功时返回写入buffer的字符数(不包括结尾的空字符\0)

失败时返回负值

代码演示

#include <stdio.h>
struct S
{char name[20];int age;float score;
};
int main()
{struct S s={"zhangsan",20,95.5f};char buffer[100]={0};sprintf(buffer,"%s %d %f",s.name,s.age,s.score);printf("%s\n",buffer);return 0;
}

5.11.2 sscanf

int sscanf(const char* str,const char* format,...);
int scanf(const char* format,...);
//从键盘上读取格式化的数据,放到变量中

功能

从字符串中读取格式化数据。它与scanf类似,但输入源是内存中的字符串而非控制台或文件。常用于解析字符串中的结构化数据(如提取文字,分割文本等)

参数

str:要解析的源字符串(输入数据来源)

format:格式化字符串,定义如何解析数据(如%d、%f、%s等)

…:可变参数列表,提供存储数据的变量地址(需与格式串中的说明符匹配)

返回值

成功时:返回成功解析并赋值的参数数量(非负值)

失败或未匹配任何数据:若输入结束或解析失败,返回EOF

代码演示

#include <stdio.h>
struct S
{char name[20];int age;float score;
};
int main()
{struct S s={"zhangsan",20,95.5f};char buf[100]={0};sprintf(buf,"%s %d %f",s.name,s.age,s.score);printf("%s\n",buffer);//还原到结构体变量中struct S t={0};sscanf(buf,"%s %d %f",t.name,&(t.age),&(t.score));//格式要对应printf("%s %f %d",t.name,t.score,t.age);//还原到结构体变量中,要按照格式打印return 0;
}

5.12总结

在这里插入图片描述

6.⽂件的随机读写

6.1 fseek

int fseek ( FILE * stream, long int offset, int origin );

功能

根据⽂件指针的位置和偏移量来定位⽂件指针(⽂件内容的光标)。

参数

FILE * stream:指向已打开文件的指针,类型为FILE*

long int offset:表示移动的字节数,类型为long

int origin:起始位置,指定偏移量的基准位置,

​ 常见选项包括:

SEEK_SET:从文件开头开始计算偏移量。

SEEK_CUR:从当前位置开始计算偏移量。

SEEK_END:从文件末尾开始计算偏移量。

返回值

成功时:返回0,表示文件指针位置已成功调整。

失败时:返回非零值(如-1),表示操作失败,可能由于文件未打开或参数无效导致。

代码演示

#include <stdio.h>  
int main () 
{ FILE * pf= fopen ( "data.txt" , "r" );if(pf==NULL){perror("fopen");return 1;}//读文件int ch=fgetc(pf);//aprintf("%c\n",ch);fseek(pf,6,SEEK_SET);//fseek(pf,5,SEEK_CUR);//fseek(pf,-3,SEEK_END);ch=fgetc(pf);//gprintf("%c\n",ch);fclose(pf);pf=NULL;return 0; 
} 

data.txt
在这里插入图片描述

写文件类似

#include <stdio.h>  
int main () 
{     FILE * pf= fopen ( "data.txt" , "r" );    if(pf==NULL)    {        perror("fopen");        return 1;    }    fputs("abcdefghi",pf);//写文件    fseek(pf,6,SEEK_SET);    //fseek(pf,5,SEEK_CUR);    //fseek(pf,-3,SEEK_END);        fputc('x',pf);fclose(pf);    pf=NULL;    return 0; 
} 

在这里插入图片描述

6.2 ftell

long int ftell ( FILE * stream );

功能

用于获取文件指针的当前位置,通常用于二进制文件或文本文件的操作中。该函数返回一个长整型值,表示文件指针相对于文件开头的偏移量。

参数

FILE * stream:指向文件对象的指针,表示需要查询位置的文件流。

返回值

成功时返回当前文件指针的位置(以字节为单位)。

失败时返回-1L,并设置errno以指示错误类型。

代码演示

#include <stdio.h>  
int main () 
{         FILE * pf= fopen ( "data.txt" , "r" );        if(pf==NULL)        {                perror("fopen");                return 1;        }            fputs("abcdefghi",pf);    //写文件        fseek(pf,-3,SEEK_END);            fputc('x',pf);int ret=ftell(pf);printf("%d\n",ret);fclose(pf);        pf=NULL;        return 0; 
} 

在这里插入图片描述

//巧妙借助这个函数算出文件内容长度
fseek(pf,0,SEEK_END);            int ret=ftell(pf);
printf("%d\n",ret);

6.3 rewind

void rewind ( FILE * stream ); 

功能

用于将文件指针重新定位到文件的开头,同时清除文件结束标志(EOF)和错误标志。它通常用于需要重新读取文件内容的场景。

参数

FILE *stream:指向文件对象的指针,表示需要重置位置的文件流。

返回值

rewind 函数没有返回值(返回类型为 void)。如果操作失败,通常是因为传入的文件指针无效或文件未正确打开,但函数本身不会显式返回错误信息。

代码演示

#include <stdio.h>  
int main () 
{         FILE * pf= fopen ( "data.txt" , "r" );        if(pf==NULL)        {                perror("fopen");                return 1;        }            fputs("abcdefghi",pf);    //写文件        fseek(pf,-3,SEEK_END);            fputc('x',pf);fseek(pf,0,SEEK_END);int ret=ftell(pf);printf("文件的字节数%d\n",ret);rewind(pf);//文件指针就回到文件的起始位置了//等价于fseek(pf,0,SEEK_END);fputc('q',pf);fclose(pf);        pf=NULL;        return 0; 
} 

结果

在这里插入图片描述

7.⽂件读取结束的判定

7.1 被错误使⽤的 feof

牢记:在⽂件读取过程中,不能⽤feof函数的返回值直接来判断⽂件的是否结束。
feof 的作⽤是:当⽂件读取结束的时候,判断是读取结束的原因是否是遇到⽂件尾结束

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

2.⼆进制⽂件的读取结束判断,判断返回值是否⼩于实际要读的个数。
例如:
• fread判断返回值是否⼩于实际要读的个数。

⽂本⽂件的例⼦:

#include <stdio.h>
#include <stdlib.h>
int main(void)
{int c; // 注意:int,⾮char,要求处理EOFFILE* fp = fopen("test.txt", "r");if(!fp) {perror("File opening failed");return EXIT_FAILURE;}//fgetc 当读取失败的时候或者遇到⽂件结束的时候,都会返回EOFwhile ((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);
}

⼆进制⽂件的例⼦:

#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 handlingif (feof(fp))printf("Error reading test.bin: unexpected end of file\n");else if (ferror(fp)) {perror("Error reading test.bin");}}fclose(fp);
}

8.⽂件缓冲区

ANSIC标准采⽤“缓冲⽂件系统”处理的数据⽂件的,所谓缓冲⽂件系统是指系统⾃动地在内存中为程序中每⼀个正在使⽤的⽂件开辟⼀块“⽂件缓冲区”。

从内存向磁盘输出数据会先送到内存中的缓冲区,装满缓冲区后才⼀起送到磁盘上。

如果从磁盘向计算机读⼊数据,则从磁盘⽂件中读取数据输⼊到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。缓冲区的⼤⼩根据C编译系统决定的。

缓冲分为:

1.完全缓冲

2.行缓冲(\n)

3.无缓冲

在这里插入图片描述

8.1 fflush

int fflush(FILE* stream);

功能

强行刷新参数stream指定流的缓冲区,确保数据写入底层设备

  • 对输出流:将缓冲区中未写入的数据立即写入文件
  • 对输入流:行为由具体实现决定,非C语言标准行为(可能清空输入缓冲区)
  • 参数为NULL时:刷新所有打开的输出流

参数

stream:指向文件流的指针(如stdout、文件指针等)

返回值

成功返回0,失败返回EOF

注意事项

1.仅对输出流或更新流(最后一次作为输出)有明确刷新行为

2.输入流的刷新行为不可移植(如清空输入缓冲区是非标准特性)

3.程序正常终止(exit)或调用fclose时会自动刷新,但程序崩溃时缓冲区数据可能丢失

代码演示

#include <stdio.h>
#include <windows.h>
//VS2022 WIN11环境测试
int main()
{FILE*pf = fopen("data.txt", "w");fputs("abcdef", pf);//先将代码放在输出缓冲区printf("睡眠10秒-已经写数据了,打开data.txt⽂件,发现⽂件没有内容\n");Sleep(10000);printf("刷新缓冲区\n");fflush(pf);//刷新缓冲区时,才将输出缓冲区的数据写到⽂件(磁盘)//注:fflush 在⾼版本的VS上不能使⽤了printf("再睡眠10秒-此时,再次打开data.txt⽂件,⽂件有内容了\n");Sleep(10000);//防止和fclose的作用混淆,先在10秒内看到结果,再关闭文件fclose(pf);//注:fclose在关闭⽂件的时候,也会刷新缓冲区pf = NULL;return 0;
}

这⾥可以得出⼀个结论:

因为有缓冲区的存在,C语⾔在操作⽂件的时候,需要做刷新缓冲区或者在⽂件操作结束的时候关闭⽂件。如果不做,可能导致读写⽂件的问题

9.更新文件

在这里插入图片描述

关键要点

1.在写完文件后,要继续读文件的时候,在读取之前一定要使用fflush()刷新文件缓冲区,或者使用fseek(),rewind()重新定位文件指示器的位置

2.在读完文件后,需要继续写文件之前,在写文件之前可以使用fseek(),rewind()重新定位文件指示器的位置

#include <stdio.h>  
int main () 
{         FILE * pf= fopen ( "text.txt" , "w+" );        if(pf==NULL)        {                perror("fopen");                return 1;        }  //写文件fputs("abcdefghi",pf);//文件内容此时在文件缓冲区fflush(pf);//刷新//读文件fseek(pf,0,SEEK_SET);//文件指示器在末尾,要重新定位int ch=fgetc(pf);printf("%c\n",ch);//想继续写文件将文件内容由abcdefghi改为abcxxxghi//文件指示器此时指向bfseek(pf,2,SEEK_CUR);fputs("xxx",pf);fclose(pf);pf=NULL;return 0;
}
http://www.dtcms.com/a/454671.html

相关文章:

  • 商业类网站的设计与制作dj网站模板免费下载
  • 深入理解AMBA总线(12)AXI突发传输和AXI控制信号
  • 校园网站推广方案怎么做手机如何登录wordpress
  • 惠州市网站建设专业制作标书公司哪家好一点
  • 外贸网站建设原则图片上传 网站建设教学视频
  • 建设营销网站的四个步骤网站建设背景图片大小的修改
  • 微网站免费创建平台建立网站账号违法行为数据库
  • 关于PyQt QChartView PyUIC自动生成问题
  • 物流网站制作新手做站必看 手把手教你做网站
  • 重庆建设工程造价信息网站wordpress免费响应式主题
  • 简述建立网站的步骤网站建设实训总结范文
  • 大模型开发 - 07 ChatClient:构建统一、优雅的大模型交互接口
  • Differential Meet-In-The-Middle Cryptanalysis
  • cc彩球网站总代理怎么做手机优化专家
  • 要网站开发费用短信怎样创建网站以及建站流程是什么
  • 市桥网站建设培训学校轻松建站
  • 做结构图的网站百度助手app下载
  • 做网站视频点播难不难临沂市住房和城乡建设局网站
  • php 网站换空间免费简历在线制作网站
  • 虚拟主机可以做几个网站创建直播平台
  • 如何做自己的淘客网站民宿网站开发方案
  • 建设网站后如何上线刚刚中国突然宣布
  • Shell脚本变量${}与命令$()替换区别
  • 本地网站搭建流程如何制作一个好网站
  • 网站建设与维护专业wordpress演示数据包
  • 企业网站建设与管理作业怎样做网站api接口
  • springboot基于javaweb的小零食销售系统的设计与实现(代码+数据库+LW)
  • 网站开发 安全电脑好用的wordpress
  • 中国网站开发的前景网站制作什么
  • 中小企业网站制作广州网络服务公司找赛合泰州城乡建设局网站