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

Linux文件IO(2):使用标准IO进行文件的打开、关闭、读写、流定位等相关操作

目录

前言

文件的打开和关闭的概念

文件的打开

文件的打开函数

文件打开的模式

文件的关闭

文件的关闭函数

注意事项

字符的输入(读单个字符)

字符输入的函数

注意事项

字符的输出(写单个字符)

字符输出的函数

注意事项

行输入(读取整个行)

行输入的函数

注意事项

行输出(写整行)

行输出的函数

二进制读写

文本文件和二进制的区别

二进制读写函数

注意事项

流的刷新

流的刷新函数

流的定位

流的定位函数

注意事项

判断流是否出错和结束

判断流是否出错和结束函数

格式化输出

格式化输出函数

格式化输入

格式化输入函数

代码练习

要求

具体实现代码

测试结果

总结


前言

上文对标准IO、流及缓冲区的概念进行介绍并进行了相关实验,上文链接点这里,本文来介绍使用标准IO进行文件的打开、关闭、读、写等相关操作。

文件的打开和关闭的概念

打开就是占用资源

关闭就是释放资源

文件的打开

文件的打开函数

FILE *fopen (const char *path, const char *mode);

path:普通文件当前路径不需要加目录,其他要使用完成的路径

mode:文件打开的模式

返回值:出错返回NULL,所以使用fopen函数必须判断是否为空

文件打开的模式

"r"或"rb"以只读方式打开文件,文件必须存在。
"r+"或"r+b"以读写方式打开文件,文件必须存在
"w"或"wb"以只写方式打开文件,若文件存在则文件长度清为0。若文件不存在则创建。
"w+"或"w+b"以读写方式打开文件,其他同"w"。
"a"或"ab"以只写方式打开文件,若文件不存在则创建;向文件写入的数据被追加到文件末尾。
"a+"或"a+b"以读写方式打开文件。其他同"a"。

文件的关闭

文件的关闭函数

int fclose(FILE *stream)

fclose()调用成功返回0,失败返回EOF(-1),并设置errno。

流关闭时自动刷新缓冲中的数据并释放缓冲区,比如:常规文件把缓冲区内容写入磁盘。

当一个程序正常终止时,所有打开的流都会被关闭。

注意事项

fclose()函数的入参stream必须保证为非空,否则出现断错误。

字符的输入(读单个字符)

字符输入的函数

int  fgetc(FILE *stream);
int  getc(FILE *stream);   //宏
int  getchar(void);

成功时返回读取的字符,若到文件末尾或出错时返回EOF(-1)。

getchar()等同于fgetc(stdin)

getc和fgetc区别就是一个时宏一个是函数

注意事项

1、函数返回值是int类型不是char类型,主要是为了扩展返回值的范围。

2、stdin也是FILE*的指针,是系统定义好的,指向的是标准输入(键盘输入)。

3、打开文件后读取,是从文件开头开始读,读完一个后读写指针会后移。

4、调用getchar会阻塞,等待你的键盘输入

字符的输出(写单个字符)

字符输出的函数

int  fputc(int c, FILE *stream);
int  putc(int c, FILE *stream);
int  putchar(int c);

成功时返回写入的字符;出错时返回EOF。

putchar(c)等同于fputc(c, stdout)。

注意事项

1、返回和输入参数都是int类型

2、遇到这种错误:Bad file descriptor,  很可能是文件打开的模式错误(只读模式去写,只写模式去读)

行输入(读取整个行)

行输入的函数

char  *gets(char *s);  读取标准输入到缓冲区s
char *fgets(char *s, int size, FILE *stream);

成功时返回s,到文件末尾或出错时返回NULL

遇到’\n’或已输入size-1个字符时返回,总是包含’\0’

注意事项

1、gets函数已经被淘汰,因为会导致缓冲区溢出

2、fgets 函数第二个参数,输入的数据超出size,size-1个字符会保存到缓冲区,最后添加’\0’,如果输入数据少于size-1 后面会添加换行符。

行输出(写整行)

行输出的函数

int  puts(const char *s);
int fputs(const char *s,  FILE *stream);

成功时返回非负整数;出错时返回EOF

puts将缓冲区s中的字符串输出到stdout,并追加’\n’

fputs将缓冲区s中的字符串输出到stream,不追加  ‘\n’

二进制读写

文本文件和二进制的区别

存储的格式不同:文本文件只能存储文本。

计算机内码概念:文本符号在计算机内部的编码(计算机内部只能存储数字0101001....,所以所有符号都要编码)

二进制读写函数

size_t fread(void *ptr, size_t size, size_t n, FILE *fp);
//void *ptr  读取内容放的位置指针
//size_t size 读取的块大小
//size_t n 读取的个数
//FILE *fp  读取的文件指针size_t fwrite(const void *ptr, size_t size, size_t n, FILE *fp);
//void *ptr  写文件的内容的位置指针
//size_t size 写的块大小
//size_t n 写的个数
//FILE *fp  要写的文件指针

注意事项

文件写完后,文件指针指向文件末尾,如果这时候读,读不出来内容。

解决办法:移动指针(后面讲解)到文件头;关闭文件,重新打开

流的刷新

流的刷新函数

int fflush(FILE *fp);

成功时返回0;出错时返回EOF。

将流缓冲区中的数据写入实际的文件。

Linux下只能刷新输出缓冲区,输入缓冲区丢弃。

如果输出到屏幕使用fflush(stdout)。

流的定位

流的定位函数

long ftell(FILE *stream);
long fseek(FILE *stream, long offset,  int whence);
void rewind(FILE *stream);

ftell()成功时返回当前读写位置,出错时返回EOF。

fseek()定位一个流,成功时返回0,出错时返回EOF。

rewind()将流定位到文件开始位置

whence参数:SEEK_SET/SEEK_CUR/SEEK_END

offset参数:偏移量,可正可负

SEEK_SET从距文件开头 offset 位移量为新的读写位置
SEEK_CUR以目前的读写位置往后增加 offset 个位移量
SEEK_END将读写位置指向文件尾后再增加 offset 个位移量

注意事项

1、打开a模式,fseek无效

2、读写流时,当前读写位置自动后移。

判断流是否出错和结束

判断流是否出错和结束函数

#include  <stdio.h>
int ferror(FILE *stream);
int feof(FILE *stream);

ferror()返回1表示流出错;否则返回

feof()返回1表示文件已到末尾;否则返回0

格式化输出

格式化输出函数

int fprintf(FILE *stream, const char *fmt, …);
int sprintf(char *s, const char *fmt, …);

成功时返回输出的字符个数;出错时返回EOF。

格式化输入

格式化输入函数

int fscanf(FILE *stream, const char *format, ...);
int sscanf(const char *str, const char *format, ...);

代码练习

要求

1、每隔1s以指定格式 “年-月-日” 分别写入文件和缓冲区;

2、该程序无限循环,直到Ctrl+C中断程序;

具体实现代码

#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <string.h>
int main(int argc,const char* argv)
{FILE *fp;time_t ctime;struct tm *ctimester;int linecount = 0;char buf[32];fp = fopen("1.txt","a+");if(fp == NULL){perror("fopen");return 0;}//calculate 1.txt  linewhile(fgets(buf,32,fp)!=NULL){if(buf[strlen(buf)-1] == '\n'){linecount++;}}while(1){ctime = time(NULL);ctimester = localtime(&ctime);printf("%04d-%02d-%02d %02d:%02d:%02d\n",ctimester->tm_year+1900,ctimester->tm_mon+1,ctimester->tm_mday,ctimester->tm_hour,ctimester->tm_min,ctimester->tm_sec);fprintf(fp,"%d, %04d-%02d-%02d %02d:%02d:%02d\n",linecount++,ctimester->tm_year+1900,ctimester->tm_mon+1,ctimester->tm_mday,ctimester->tm_hour,ctimester->tm_min,ctimester->tm_sec);fflush(fp);sleep(1);}fclose(fp);return 0;
}

测试结果

总结

本文总结了C语言标准IO的输入、输出、读写、流的刷新定位等相关概念及函数介绍,并根据这些函数进行了一个包含文件打开关闭、读写、格式化输出等内容的实现。

相关文章:

  • 基于Java在线考试系统系统设计与实现(源码+部署文档)
  • 算法---动态规划练习-6(地下城游戏)
  • ​马来语翻译中文去哪比较好?
  • 反序列化动态调用 [NPUCTF2020]ReadlezPHP1
  • Redis 特性,为什么要用Redis,Redis到底是多线程还是单线程
  • 如何使用 ArcGIS Pro 制作三维建筑
  • Spring和Spring Boot之间的区别
  • 非wpf应用程序项目【类库、用户控件库】中使用HandyControl
  • IDEA设置内存大小不生效
  • 二、数据库管理员密码管理
  • CSS及javascript
  • Oracle AI Vector Search Multi-Vector Similarity Search 即多向量相似度检索学习笔记
  • 解决PATH变量污染的问题
  • 银河麒麟服务器操作系统V10SP1在登录界面显示启动会话失败
  • 2024蓝桥杯每日一题(背包)
  • 分享的文章《人生如棋》
  • 《微软的软件测试之道》成书始末、出版宣告、补充致谢名单及相关信息
  • 【个人向】《HTTP图解》阅后小结
  • 【跃迁之路】【519天】程序员高效学习方法论探索系列(实验阶段276-2018.07.09)...
  • 08.Android之View事件问题
  • Apache的80端口被占用以及访问时报错403
  • C++类的相互关联
  • JS函数式编程 数组部分风格 ES6版
  • Sublime Text 2/3 绑定Eclipse快捷键
  • 从重复到重用
  • 七牛云假注销小指南
  • 微信小程序--------语音识别(前端自己也能玩)
  • 小程序测试方案初探
  • AI又要和人类“对打”,Deepmind宣布《星战Ⅱ》即将开始 ...
  • 组复制官方翻译九、Group Replication Technical Details
  • ###51单片机学习(2)-----如何通过C语言运用延时函数设计LED流水灯
  • (Bean工厂的后处理器入门)学习Spring的第七天
  • (C语言)深入理解指针2之野指针与传值与传址与assert断言
  • (附源码)计算机毕业设计ssm-Java网名推荐系统
  • (论文阅读30/100)Convolutional Pose Machines
  • (已解决)什么是vue导航守卫
  • (原創) 人會胖會瘦,都是自我要求的結果 (日記)
  • .mkp勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .NET 6 Mysql Canal (CDC 增量同步,捕获变更数据) 案例版
  • .NET Conf 2023 回顾 – 庆祝社区、创新和 .NET 8 的发布
  • .NET 发展历程
  • .net 流——流的类型体系简单介绍
  • .NET框架类在ASP.NET中的使用(2) ——QA
  • .NET使用存储过程实现对数据库的增删改查
  • .NET是什么
  • .NET与 java通用的3DES加密解密方法
  • .Net转前端开发-启航篇,如何定制博客园主题
  • /etc/X11/xorg.conf 文件被误改后进不了图形化界面
  • @Transactional注解下,循环取序列的值,但得到的值都相同的问题
  • [20161101]rman备份与数据文件变化7.txt
  • [android] 练习PopupWindow实现对话框
  • [ANT] 项目中应用ANT
  • [C++] 多线程编程-thread::yield()-sleep_for()
  • [CISCN2019 华东北赛区]Web2
  • [Excel] vlookup函数