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

Linux应用(2)——标准IO

一、简介

第一类:C语言阶段操作过的--只能对特殊文件操作
scanf  printf   getchar putchar  gets  puts
第二类:新增的--可以对特殊文件操作,也可以是对普通文件操作
fopen   fclose   fread  fwrite  fseek
fscanf   fprintf  fgetc  fputc   fgets  fputs
feof   fflush

1.1 文件IO特点

  1. 文件IO可以对普通文件操作,也可以对特殊文件操作
  2. 文件会存在文件指针,当open打开文件时,文件指针默认在文件开始处,对文件的读写,都会造成文件指针的偏移(以字节为单位),当close关闭后,文件指针默认在文件末尾
  3. 文件IO的读写函数没有缓冲区,读写是马上生效的,是一种低速IO
  4. read 输入--> 文件数据的读取  write 输出--->数据存放到文件

1.2 标准IO特点

  1. 标准IO可以对普通文件操作,也可以对特殊文件操作
  2. 文件会存在文件指针,当fopen打开文件时,文件指针默认在文件开始处,对文件的读写,都会造成文件指针的偏移(以字节为单位),当fclose关闭后,文件指针默认在文件末尾
  3. 标准IO的读写函数存在缓冲区,读写不会马上生效,当满足条件才生效,是一种高速IO
  4. 标准IO存在多种读写方式,读函数---输入   写函数---输出
    标准IO 的读写通常配套使用
    第一对读写:fscanf   fprintf   格式化读写
    第二对读写:fgetc  fputc     单字符读写
    第三对读写:fgets  fputs     字符串读写
    第四对读写:fread  fwrite    全缓存读写

1.3 缓存特点

分类:

---针对的读写函数
无缓存: 文件IO  中的  read  write
行缓存:   标准IO  剩余的都是行缓存
scanf  printf   getchar putchar  gets  puts
fscanf   fprintf  fgetc  fputc   fgets  fputs
全缓存:   标准IO   fread  fwrite

行缓存满足条件
在常规开发过程中,用户无需记忆缓存的满足条件,因为默认常规下都是满足的
------满足以下任意一个即可
输入输出存在换行符 

输入: ---回车结束;

输出: ---输出 ‘\n’

  1. 程序自然结束,没有死循环
  2. 程序中采用 fclose关闭文件
  3. 程序中采用fflush 刷新缓冲区
  4. 写满该行  大致 1024字节

全行缓存满足条件

 ------满足以下任意一个即可

  1. 程序自然结束,没有死循环
  2. 程序中采用 fclose关闭文件
  3. 程序中采用fflush 刷新缓冲区
  4. 写满全缓存  大致 4K 字节

1.4 文件IO与标准IO对比

对比

文件IO

标准IO

用途上

用途1:实现应用层数据的存取,不丢失

用途2:实现驱动和应用的数据交流

用途1:实现应用层数据的存取,不丢失 用途2: 实现驱动和应用的数据交流

对文件操作上

可以对普通文件操作,也可以对特殊文件操作;普通文件需要先打开在读写;特殊文件直接读写

可以对普通文件操作,也可以对特殊文件操作;普通文件需要先打开在读写;特殊文件直接读写

文件指针

文件会存在文件指针,当open打开文件时,文件指针默认在文件开始处,对文件的读写,都会造成文件指针的偏移(以字节为单位),当close关闭后,文件指针默认在文件末尾

文件会存在文件指针,当fopen打开文件时,文件指针默认在文件开始处,对文件的读写,都会造成文件指针的偏移(以字节为单位),当fclose关闭后,文件指针默认在文件末尾

缓冲区

无缓存,读写马上生效,低速IO

有缓存,读写满足条件才生效,高速IO

文件ID

int fd   文件描述符

FILE *fp  文件流指针

应用平台

#include <unistd.h>

只能在linux环境下运行

#include <stdio.h>

可以在linux环境下运行,也可以在win下运行

特殊文件

文件IO--文件描述符/fd

标准IO--文件流指针/fp

标准输入

0

stdin

标准输出

1

stdout

标准错误

2

stderr

普通文件

默认从3开始分配

二、函数

2.1 fopen,fclose

打开/关闭函数应用

头文件   :#include<stdio.h>
函数原型:FILE * fopen(const char * path,const char * mode)
函数参数:
@param1
      const char * path  : 带路径的文件名
@param2
const char * mode : 打开权限
r  :  只读方式,打开已存在的文件
w :  覆盖方式打开只写文件,如果文件存在就覆盖在打开,如果文件不存在就创建
a : 追加方式打开只写文件,如果文件存在就追加在打开,如果文件不存在就创建
      +: 可读可写
      b : 以二进制方式
r+  可读可写方式,打开已存在的文件
w+ 覆盖方式打开 可读可写文件,如果文件存在就覆盖在打开,如果文件不存在就创建
a+ 追加方式打开可读可写文件,如果文件存在就追加在打开,如果文件不存在就创建
注意事项:  'r'   错误的   ; "r"   正确的
函数返回值:
成功: 返回文件的ID--文件流指针
失败:  NULL
函数功能:以指定方式(是否存在、文件权限) 打开文件
函数特性:
fopen成功后,文件指针默认在文件开始处
可以利用对同个文件的多次打开,实现把文件指针偏移到文件开始处;同样也可以利用fseek函数实现

头文件:#include<stdio.h>
函数原型:int fclose(FILE * stream);
函数参数:FILE * stream   文件流指针
函数返回值: 应用不多
若关文件动作成功则返回 0,有错误发生时则返回 EOFstruct _IO_FILE {
函数功能:关闭文件

2.2 fgetc,fputc

单字节读写函数应用

头文件 #include<stdio.h>
函数原型:int fgetc(FILE * stream); 
函数参数:FILE * stream 文件流指针, 从哪个文件中读取数据
函数返回值:读到的字符;如果 返回 EOF就说明到文件尾部
函数功能:从文件中读取一个字节数据--读函数--输入---数据 从文件到应用 buf
函数特性:
读操作会引起文件指针的偏移
int ch = fgetc(stdin);  等价于   int  ch=getchar();

头文件:#include<stdio.h>
函数原型:int fputc(int c,FILE * stream);
函数参数:
@param1
 int c  : 要写入的字符
 @param2 FILE * stream: 文件流指针,要写到哪个文件中
函数返回值:--应用不多
返回写入成功的字符
函数功能:把一个字符写入文件---写函数--输出---数据 从 应用 buf 到文件
函数特性:
写操作会引起文件指针的偏移
fputc('\n',stdout);   等价于   putchar('\n');

2.3 fgets ,fputs

字符串读写函数应用

头文件:#include<stdio.h>
函数原型:char * fgets(char * s,int size,FILE * stream);
函数参数:
@param1   
char * s :  应用层 buf 数组
@param2   int size : 一次读取的字节数
@param3   FILE * stream: 文件流指针--从哪个文件读
函数返回值:
成功则返回 s 指针,
返回 NULL 则表示有错误发生。
函数功能:读函数---输入--数据从 文件 到 buf ,从FILE * stream文件中读取size字节到应用层s所指向的内存中
函数特性:
读操作会引起文件指针的偏移
函数返回值不能作为读取到文件尾部的判断依据,需要借助于其他函数 feof

头文件:#include<stdio.h>
函数原型:int fputs(const char * s,FILE * stream);
函数参数:
@param1  const char * s:  内存
@param2  FILE * stream :  文件
函数返回值:应用不多  ,int  实际写入的字符个数
函数功能:写函数--输出---数据从内存s到文件 把内存s中的所有有效字符 输出到 stream文件中
函数特性:
写操作会引起文件指针的偏移
写入函数无指定 size字节数,是把s内存地址中所有有效字符都写入
---所以在使用fgets ,fputs 最好保证 一次读写的字节数相同

注意事项:
fgets  fputs  这对字符串读写 应用不多--使用麻烦
1.fgets函数返回值不能作为文件尾部的判断依据,需要额外引入feof函数
2.fputs函数无指定写入字节数,是把所有有效字符都写入,需要注意应写入的字节个数

2.4 fscanf  fprintf 

格式化读写函数应用

头文件:#include<stdio.h>
函数原型:
int fscanf(FILE * stream ,const char *format,....);
int scanf(                      ,const char *format,....);//  相当于文件流指针固定是  stdin
函数参数:
@param1   FILE * stream : 文件流指针--读哪个文件
@param2  const char *format: 格式化控制 %c   %d  %f  %s
....  : 内存地址列表
函数返回值:使用不多 成功则返回参数数目,失败则返回-1,
函数功能:从指定文件中格式化读取数据到内存--取
函数特性:
1.读操作会引起文件指针的偏移
2.要借助于 feof函数对文件尾部判断
int  num;float sorce;char buf[20];
scanf("%d %f %s",&num,&sorce,buf); 等价于fscanf(stdin ,"%d %f %s",&num,&sorce,buf);

头文件:#include<stdio.h>
函数原型:int fprintf(FILE * stream, const char * format,.......);
函数参数:
@param1 
FILE * stream : 文件流指针--写到哪个文件
@param2 const char *format:格式化控制 %c   %d  %f  %s
....                          : 输出列表
函数返回值:使用不多,成功则返回实际输出的字符数目,失败则返回-1,
函数功能:把内存中格式化数据写入到文件--存
函数特性:1.写操作会引起文件指针的偏移

2.5 printf  fprintf sprintf 对比

int fprintf(FILE * stream, const char * format,.......);  // 格式化输出到指定文件
int printf( ,const char *format,....);                             // 格式化输出到屏幕
int sprintf(char *buf , const char * format,.......);      //格式化输出到char buf中-实际上就是实现 int/float 转换成 char

2.6 fflush feof

头文件:#include<stdio.h>
函数原型:int fflush(FILE* stream);
函数参数:FILE* stream: 文件流指针
函数返回值:成功返回 0,失败返回 EOF
函数功能:刷新缓存区

头文件 #include<stdio.h>
函数原型:int feof(FILE * stream);
函数参数:FILE * stream: 文件流指针--要检测的文件
函数返回值:
==0: 没有到文件尾部
!=0:    已到达文件尾
函数功能:判断是否已经到文件尾部

2.7 fread,fwrite全缓存读写函数

头文件:#include<stdio.h>
函数原型:size_t fread(void * ptr,size_t size,size_t nmemb,FILE * stream);
函数参数:
  @param1:void * ptr  :  应用层内存buf
  @param2: size_t size  : 每块的字节数 
  @param3: size_t nmemb: 读取的块数
  @param4 FILE* stream: 文件流指针--从哪个文件中读
一次读取的字节总数= nmemb *size
函数返回值:可以作为文件尾部的判断依据
返回实际读取到的 nmemb 数目
函数功能:读函数--输入--数据从文件到内存buf ,从文件中读取内容到应用内存buf

头文件:#include<stdio.h>
函数原型:size_t fwrite(const void * ptr,size_t size,size_t nmemb,FILE * stream);
函数参数:
@param1 
constvoid * ptr  :  应用层内存buf
   @param2 size_t size  : 每块的字节数 
   @param3 size_t nmemb: 写入的块数
   @param4 FILE* stream: 文件流指针--要写到哪个文件
一次读取的字节总数= nmemb *size
函数返回值:使用不多
返回实际写入的 nmemb 数目
函数功能:写函数--输出--数据从内存buf 到文件,把应用内存buf中的数据存入文件

三、练习

1.利用标准io实现fgetc  fputc  实现  cp 拷问文件命令的重写

/*利用标准io实现fgetc  fputc  实现  cp 拷问文件命令的重写*/
#include <stdio.h>int main(int argc,char *argv[])
{//定义文件流指针FILE*fpsrc,*fpobj;//定义接收用int ch;if(argc!=3){printf("复制格式错误!\n");return -1;}//打开源文件,源文件必须存在fpsrc=fopen(argv[1],"r");if(fpsrc==NULL){printf("源文件打开失败!\n");return -1;}//打开目标文件,目标文件不存在fpobj=fopen(argv[2],"w");if(fpobj==NULL){printf("目标文件打开失败!\n");return -1;}while(1){//从源文件中读内容ch=fgetc(fpsrc);if(ch==EOF)break;//将读到的内容放到目标文件fputc(ch,fpobj);}fclose(fpsrc);fclose(fpobj);return 0;
}

2.利用标准io实现fgets  fputs  实现  cat 命令的重写

/*利用标准io实现fgets fputs实现cat命令的重写*/
#include <stdio.h>int main(int argc,char *argv[])
{//定义文件流指针FILE*fpsrc;//定义接收用char recvbuff[20];//定义用于接收返回值char*p=NULL;if(argc!=2){printf("查看格式错误!\n");return -1;}//打开源文件,源文件必须存在fpsrc=fopen(argv[1],"r");if(fpsrc==NULL){printf("源文件打开失败!\n");return -1;}while(1){//从源文件中读内容到数组中p=fgets(recvbuff,20,fpsrc);//当有错误或者读到末尾返回if(p==NULL||feof(fpsrc)==!0)break;//将读到的内容放到目标文件fputs(recvbuff,stdout);}fclose(fpsrc);return 0;
}

3.构造一个学员信息的结构体,包含 姓名 学号 成绩 等成员;编写函数,通过键盘输入3个学员的信息并格把所有信息和学员总数格式化存入文件;---学员总数占一行  每个学生信息占一行然后从文件中读取每个学员的信息并打印

/*构造一个学员信息的结构体,包含 姓名 学号 成绩 等成员;编写函数,通过键盘输入3个学员的信息并格把所有信息和学员总数格式化存入文件;---学员总数占一行  每个学生信息占一行然后从文件中读取每个学员的信息并打印*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct ST
{int num;float socer;char name[20];
}STU;int main()
{STU stu[3];FILE*fp;int num=0;fp=fopen("./1.txt","w+");if(fp==NULL){printf("open error\n");return -1;}//先存入学生总数fprintf(fp,"%d\n",3);//键盘得到信息并存入结构图题中for(int i=0;i<3;i++){printf("请输入第%d个学生的姓名",i+1);scanf("%s",stu[i].name);printf("请输入第%d个学生的学号,成绩",i+1);scanf("%d %f",&stu[i].num,&stu[i].socer);//向1.txt中存入信息fprintf(fp,"%s\t%d\t%f\n",stu[i].name,stu[i].num,stu[i].socer);}//关闭文件fclose(fp);//重新打开文件,使文件指针回到文件开始处fp=fopen("./1.txt","r");if(fp==NULL){printf("open error\n");return -1;}//清空结构体内容memset(stu,0,sizeof(STU)*3);//读取信息fscanf(fp,"%d\n",&num);//将1.txt中的文件输入到numprintf("num=%d\n",num);for(int i=0;i<num;i++){fscanf(fp,"%s\t%d\t%f\n",stu[i].name,&stu[i].num,&stu[i].socer);//将1.txt中的文件输入到结构体printf("姓名%s,学号%d,成绩%f\n",stu[i].name,stu[i].num,stu[i].socer);}return 0;
}


文章转载自:

http://JXA5N3BU.tpyrn.cn
http://jgBujaa7.tpyrn.cn
http://GM2Che0O.tpyrn.cn
http://cPBXlGut.tpyrn.cn
http://LFyFebvF.tpyrn.cn
http://OkHM0sFA.tpyrn.cn
http://0cUOrhHA.tpyrn.cn
http://ZPGHUpad.tpyrn.cn
http://RV9PkZYq.tpyrn.cn
http://ICE4YZoL.tpyrn.cn
http://Aigb4wcA.tpyrn.cn
http://kEMUNBu1.tpyrn.cn
http://dg4cuwoV.tpyrn.cn
http://XgR0kT99.tpyrn.cn
http://n8uZlA7y.tpyrn.cn
http://iqWoO5FJ.tpyrn.cn
http://OrVwqz5X.tpyrn.cn
http://idi3WKHs.tpyrn.cn
http://F14QaUjt.tpyrn.cn
http://3mhi92gD.tpyrn.cn
http://riot5vlO.tpyrn.cn
http://BLxtUM2N.tpyrn.cn
http://8ZD5s0vH.tpyrn.cn
http://XYFuaRVf.tpyrn.cn
http://CmZoTTxL.tpyrn.cn
http://2dZBYBFq.tpyrn.cn
http://eOIGtU3E.tpyrn.cn
http://6MMlXwCA.tpyrn.cn
http://negTkXci.tpyrn.cn
http://kSUPeb0s.tpyrn.cn
http://www.dtcms.com/a/368439.html

相关文章:

  • 面试官问:你选择这份工作的动机是什么?
  • 大型语言模型SEO(LLM SEO)完全手册:驾驭搜索新范式
  • Onlyoffice集成与AI交互操作指引(Iframe版)
  • 前端视觉交互设计全解析:从悬停高亮到多维交互体系(含代码 + 图表)
  • 【基础组件】手撕 MYSQL 连接池(C++ 版本)
  • 【FastDDS】Layer Transport ( 01-overview )
  • 算法备案全流程-纯干货
  • Linux 进程信号的产生
  • 【华为Mate XTs 非凡大师】麒麟芯片回归:Mate XTs搭载麒麟9020,鸿蒙5.1体验新境界
  • Swift 解题:LeetCode 372 超级次方(Super Pow)
  • 深入理解 JVM 字节码文件:从组成结构到 Arthas 工具实践
  • C# 阿里云 OSS 图片上传步骤及浏览器查看方法
  • JVM新生代和老生代比例如何设置?
  • 基于OpenGL封装摄像机类:视图矩阵与透视矩阵的实现
  • MySQL 8.0.36 主从复制完整实验
  • 无需bootloader,BootROM -> Linux Kernel 启动模式
  • 【Vue3+TypeScript】H5项目实现企业微信OAuth2.0授权登录完整指南
  • 为什么MySQL可重复读级别不能完全避免幻读
  • Gradle Task 进阶:Task 依赖关系、输入输出、增量构建原理
  • 串口通信基础知识
  • webshell及冰蝎双击无法打开?
  • Doris 数据仓库例子
  • 从零构建企业级LLMOps平台:LMForge——支持多模型、可视化编排、知识库与安全审核的全栈解决方案
  • 如何根据Excel数据表生成多个合同、工作证、录取通知书等word文件?
  • Highcharts 数据源常见问题解析:连接方式、格式处理与性能优化指南
  • T06_RNN示例
  • 【Android】Room数据库的使用
  • CoolGuard风控系统配置评分卡、权重策略|QLExpress脚本
  • 【FastDDS】Layer Transport ( 02-Transport API )
  • 确保 SQL Server 备份安全有效的最佳实践