标准IO及其各函数用法

2023-10-30

目录

综述标准IO与文件IO

1、fopen 函数(打开一个文件)

2、fclose函数(关闭流)

3、读写函数

3.1按字符读写

3.1.1 fgetc函数(从指定流中读取一个字符)

3.1.2 fputc函数(向流中输出一个字符)

3.1.3案例操作

3.2按行读写

3.2.1 fgets函数(按行读文件)

3.2.2 fputs函数(向文件中输出一串字符串)

3.2.3 小结

3.3按块读写

3.3.1 fread函数(按块读取内容)

3.3.2 fwrite函数(按块向流中写入数据)

3.3.3总结

4、perror函数

5、fseek、ftell、rewind函数


综述标准IO与文件IO

标准IO:

使用时在用户空间创建缓冲区,在合适的时机在通过系统调用访问实际的文件,从而减少了使用系统调用的次数。

缓存方式分三种:

行缓冲:\n

全缓冲:缓存区填满内容才会溢出

不缓存:stderr

流:

当使用标准IO打开一个文件时,就会创建一个FILE结构体描述该文件,我们把这个FILE结构体形象的称为流,标准IO函数都是基于流进行各种操作。

文件指针:

指向一个打开文件的指针(硬盘中的文件被拷贝到内存中之后,会以FILE结构体的形态存在,要操作该文件必须使用文件指针)

FILE:

C语言file类,在stdio.h 头文件中,FILE类是一个结构体:定义如下:

struct _iobuf {
        char *_ptr;
        int   _cnt;
        char *_base;
        int   _flag;
        int   _file;
        int   _charbuf;
        int   _bufsiz;
        char *_tmpfname;
        };
typedef struct _iobuf FILE;

通过typedef定义了 文件类型 的别名: “FILE”,这样以后需要读写文件的时候直接就可以用FILE去定义。

文件IO:

1、不带缓存

2、通过文件描述符来访问文件

文件IO与标准IO的区别

  1. 文件IO又被称为低级磁盘IO,遵循POSIX相关标准,任何兼容POSIX标准的操作系统上都支持文件IO。标准IO被称为高级磁盘IO,遵循ANSI C标准,只要开发环境中有标准C库,就可以使用标准IO。
  2. 文件IO读写文件时,每次操作都会执行相关的系统调用,这样可以直接读取实际文件,但是频繁的系统调用会增加系统的开销。标准IO可以看做是在文件IO的基础上封装了缓冲机制,从而减少了系统调用的次数。
  3. 文件IO中用文件描述符表示一个打开的文件,可以访问不同类型的文件。而标准IO使用流表示一个打开的文件,只能访问普通文件

再来回顾一下各个文件类型

普通件 -

管道文件 p

链接文件 l

目录文件 d

套接字文件 s

块设备文件 b

字符设备文件 c

1、fopen 函数(打开一个文件)

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

FILE *fopen(要打开的文件路径及文件名, 以何方式打开 )

打开方式:r(只读)、w(只写)、a(追加写入)、r+(读写)、w+(读写)

返回值:成功,返回已经打开的文件流指针,失败返回NULL

2、fclose函数(关闭流)

int fclose(FILE *fp)

int fclose(已经打开的文件流指针)

返回值:

成功返回0

失败返回-1(EOF)(end of file,文件尾部的意思)

注意:EOF只能判断是否到文本文件的末尾,不能判断是否到二进制文件的末尾

判断是否关闭的代码

if (fclose(fp) != 0)

{

 printf("Error in closing file %s\n", str1);

}

以下是使用fopen和fclose的案例

99786363a1b149148d7dfcaa35d6c4c2.png

9312261c568d4a50af1f62b0383665b0.png

说明:

 ../2.txt表示上一级目录下的2.txt文件,此处按照实际情况来写就行。

errno.h头文件定义了通过错误码来回报错误资讯的宏。errno 宏定义为一个 int 型态的左值, 包含任何函式使用errno功能所产生的上一个错误码。

所以这里用的是%d这个格式控制符。

3、读写函数

当程序运行起来时,有三个文件默认已经打开,标准输入、标准输出、标准出错,对应的流指针分别为:stdin、stdout、stderr,这几个都是从键盘输入,终端输出,此次我们重点介绍的是从文件中读取,以及写入文件中。

3.1按字符读写

getchar( )、putchar( ) 只能从键盘输入

fgetc( )、fputc( ) 从哪里输入都可以:键盘、文件都可输入

3.1.1 fgetc函数(从指定流中读取一个字符)

int fgetc(FILE *stream)

int fgetc(指定的流),参数是读取字符的流来源

这个流可以写stdin,就是从键盘流输入,如果要用其他的流,从文件中读取和写入,需自己定义

返回值:成功返回输出的字符的ASCII值,失败返回-1

这个函数的返回值,是返回所读取的一个字节。如果读到文件末尾或者读取出错时返回EOF 

3.1.2 fputc函数(向流中输出一个字符)

int fputc(int c, FILE *stream);

int fputc(要输出的字符变量名, 要输出到哪的流?);

返回值:成功返回输出的字符的ASCII值,失败返回-1

案例:

7bb1e57875194c0db96cd22236d94206.png

89e293ac1297454297eb5122b965fd49.png

说明:

这里用的stdin 是标准输入流、stdout是标准输出流这两个流,以及stderr在程序运行一开始就会自己开启,我们可以直接拿来用,体现的是一种键盘与终端的关系

3.1.3案例操作

用字符的读写模拟完成CP命令,如下:

d1a780e7be6b4c31b20c31f184f357bb.png

26d0cd5805664727aa200b3d72689aef.png

3.2按行读写

3.2.1 fgets函数(按行读文件)

char *fgets(char *s, int size, FILE *stream)

char *fgets(读到内容放哪个地址, 能放的空间大小, 要操作的流(读它内容))

参数:

     s: 字符型指针,指向存储读入数据的缓冲区的地址

     size: 从流中读入n-1个字符

     stream : 指向读取的流

返回值:

成功,返回读到缓冲区字符串的首地址,

失败,返回NULL遇到文件结尾也是返回NULL

注意:1、最多读size-1个字节

因为它遇到换行符,会将换行符也读入

3.2.2 fputs函数(向文件中输出一串字符串)

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

int fputs(内存空间的首地址, 要操作的流)

返回值:

成功返回非负整数

失败返回-1

3.2.3 小结

总结:fgets和gets有什么区别

fgets比gets安全

fgets会读取换行符,而gets不会

puts和fputs的区别

puts会自动换行,而fputs不会

3.3按块读写

3.3.1 fread函数(按块读取内容

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)

size_t fread(接收保存数据的地址, 要读出内容的单字节数, 要进行读出size字节的数据项的个数, 要操作的流(目标文件指针))

fread函数每次从stream中最多读取nmemb个单元,每个单元大小为size个字节,将读取的数据放到ptr,文件流的指针后移size*nmemb字节。

由于每次移动的是size*nmemb,可以想象成二维变动(有两个变量值),所以我们叫它块读取

54160d0cb7ae4be5908bec1f2d3e2a98.png​ 

fread函数,每一次若读取成功,返回的是nmemb数值(这个值是我们自己设置的),如果返回值比nmemb要小,则可能是出错或者读取结束。

他还说到,fread函数无法区分是出错或者读取结束,需要借助feof函数或者ferror函数去进一步判断。

经验证,fread函数的返回值成功都是返回设定的nmemb值大小,只在最后一次,剩余的量不足以够nmemb,所以会返回一个比nmemb要小的值

84ed0f95851c42fea81fc0ead01aa4a5.png

 a580883579824c2680ac4b439524fd79.png

feof函数用于检测是否到达文件末尾,如果到末尾,则返回是一个非零数。

3.3.2 fwrite函数(按块向流中写入数据)

size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream)

size_t fwrite(内存空间首地址, 要写入内容的单字节数, 要进行写入size字节的数据项的个数,要操作的流)

size是sizeof(char),如果是char类型的,后一个参数是总的个数

返回值:

成功,返回写入的块数

失败,返回-1

3.3.3总结

此处用字符读写、按行读写、按块读写,模拟了虚拟机的CP命令,读者可以进行对比学习

文件操作基本步骤:

①打开文件

②操作文件

③关闭文件

#include<stdio.h>
#include<errno.h>
int main(int argc,char *argv[])
{
	//入参检测
	if(argc < 3)
	{
		printf("try again");
		return -1;
	}
	//打开文件
	FILE *fr=fopen(argv[1],"r");
	FILE *fw=fopen(argv[2],"w");
	if((NULL == fr) || (NULL == fw))
	{
		printf("open error:%d\n",errno);
		return -1;
	}
/*
	//文件操作(模拟cp命令,通过字符读写)
	char ch;
	while(1)
	{
		ch = fgetc(fr);	
		if(EOF == ch)
		{
			break;
		}
		fputc(ch,fw);
	}
	//文件操作(模拟CP,通过行读写)
	char buf[10]="0";
	char *p=NULL;
	while(1)
	{
		p=fgets(buf,10,fr);		
		if(NULL == p)
		{
			break;
		}
		fputs(buf,fw);	
	}
*/
	//文件操作(模拟CP,通过块读写)
	char buf[50]="0";
	int test1,test2;
	while(1)
	{
		test1=fread(buf,1,15,fr);
		test2=feof(fr);
		//printf("fread的返回值:%d\n",test1);
		//printf("feof的返回值:%d\n",test2);
		if(test1 < 0)
		{
			perror("fread error");
			return -1;
		}
	    else if(test2 != 0)
		{
			break;
		}
		fwrite(buf,1,15,fw);
	}
	//关闭文件
	fclose(fr);
	fclose(fw);
	return 0;
}

4、perror函数

函数定义:

void perror(const char *s);

使用:

perror ("open_port");

包含头文件(不可以掉了这个头文件):

#include <stdio.h>//包含perror的头文件

功能:perror ( )用 来 将 上 一 个 函 数 发 生 错 误 的 原 因 输 出 到 标 准 设备 (stderr) 。参数 s 所指的字符串会先打印出,后面再加上错误原因字符串。

5、fseek、ftell、rewind函数

首先,我们需要知道一点,文件在被操作时,文件指针会在文件内部自己移动

这三个函数都包含于stdio.h头文件中

函数的形式分别为:

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

long ftell(FILE *stream);

Void rewind(FILE *stream);

 函数

功能

返回值

fseek

重定位流上的文件指针

成功返回0

失败返回-1

ftell

获取当前文件指针位置

成功返回文件指针位置

失败返回-1

rewind

将文件内部指针重新指向文件的开头

无返回值 

fseek的 whence参数设置,可以写英文,也可以写0,1,2,分别依次对应

起始点

代表的文件位置

对应数字

SEEK_SET

文件开头

0

SEEK_CUR

文件当前位置

1

SEEK_END

文件末尾

2

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

标准IO及其各函数用法 的相关文章

  • 如何为 Linux 桌面条目文件指定带有相对路径的图标?

    对于我的一个 Linux 应用程序 我有应用程序二进制文件 一个 launcher sh 脚本 针对 LD LIBRARY PATH 和一个 desktop 文件 所有这些都位于同一文件夹中 我想使用图标的相对路径而不是绝对路径 我试过了
  • python获取上传/下载速度

    我想在我的计算机上监控上传和下载速度 一个名为 conky 的程序已经在 conky conf 中执行了以下操作 Connection quality alignr wireless link qual perc wlan0 downspe
  • 在 Linux 上以编程方式设置 DNS 名称服务器

    我希望能够通过我的 C C 程序为 Linux 上的 DNS 名称服务器添加 IP 地址 我在一个带有只读 etc resolv conf 的嵌入式平台上 这意味着我不能简单地将 nameserver xxx xxx xxx xxx 行添加
  • Linux 上的静态 Qt5 构建:部署时如何处理字体?

    我使用这些配置选项创建了 Qt 5 2 0 库的静态版本 Ubuntu 12 04 开源 确认许可 force pkg config 发布 静止的 前缀 home juzzlin qt5 无icu opengl桌面 无油嘴滑舌 辅助功能 n
  • 使用循环在 C 中管道传输两个或多个 shell 命令

    我正在尝试执行ls wc l通过 C 语言程序 而不是使用命令行 这是我当前的工作代码 int main int pfds 2 pipe pfds pid t pid fork if pid 0 The child process clos
  • 使用 MAX_ORDER / 包含 mmzone.h

    根据https www kernel org doc Documentation networking packet mmap txt https www kernel org doc Documentation networking pa
  • 从 Xlib 转换为 xcb

    我目前正在将我的一个应用程序从 Xlib 移植到 libxcb 但在查找有关我有时使用的 XInput2 扩展的信息时遇到了一些麻烦 libxcb 中有 XInput2 实现吗 如果是的话 在哪里可以找到文档 目前我在使用此功能时遇到问题
  • 与 pthread 的进程间互斥

    我想使用一个互斥体 它将用于同步对两个不同进程共享的内存中驻留的某些变量的访问 我怎样才能做到这一点 执行该操作的代码示例将非常感激 以下示例演示了 Pthread 进程间互斥体的创建 使用和销毁 将示例推广到多个进程作为读者的练习 inc
  • 如何在 Linux 中使用 C 语言使用共享内存

    我的一个项目有点问题 我一直在试图找到一个有据可查的使用共享内存的例子fork 但没有成功 基本上情况是 当用户启动程序时 我需要在共享内存中存储两个值 当前路径这是一个char and a 文件名这也是char 根据命令参数 启动一个新进
  • linux下如何从文本文件中获取值

    我有一些文本格式的文件 xxx conf 我在这个文件中有一些文本 disablelog 1 当我使用 grep r disablelog oscam conf 输出是 disablelog 1 但我只需要值1 请问你有什么想法吗 一种方法
  • Linux/POSIX:为什么 fork() 不分叉*所有*线程

    众所周知 POSIX下创建新进程的默认方式是使用fork 在 Linux 下 这在内部映射到clone 我想知道的是 众所周知 当一个人打电话时fork 子进程是用单个线程创建的 调用的线程fork cf https linux die n
  • 我什么时候应该编写 Linux 内核模块?

    有些人出于某种原因想要将 Linux 中的代码从用户空间移动到内核空间 很多时候 原因似乎是代码应该具有特别高的优先级 或者只是 内核空间更快 这对我来说似乎很奇怪 我什么时候应该考虑编写内核模块 有一套标准吗 我怎样才能激励将代码保存在
  • 检查已安装的软件包,如果没有找到则安装

    我需要检查已安装的软件包 如果未安装则安装它们 RHEL CentOS Fedora 示例 rpm qa grep glibc static glibc static 2 12 1 80 el6 3 5 i686 如何在 BASH 中进行检
  • 复制目录内容

    我想将目录 tmp1 的内容复制到另一个目录 tmp2 tmp1 可能包含文件和其他目录 我想使用C C 复制tmp1的内容 包括模式 如果 tmp1 包含目录树 我想递归复制它们 最简单的解决方案是什么 我找到了一个解决方案来打开目录并读
  • x86-64 AMD 上 CALL 指令的操作数生成

    以下是示例程序 objdump 的输出 080483b4
  • 使用自定义堆的类似 malloc 的函数

    如果我希望使用自定义预分配堆构造类似 malloc 的功能 那么 C 中最好的方法是什么 我的具体问题是 我有一个可映射 类似内存 的设备 已将其放入我的地址空间中 但我需要获得一种更灵活的方式来使用该内存来存储将随着时间的推移分配和释放的
  • 嵌入式 Linux – 部署固件更新的机制? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我正在考虑在 Yocto 项目上开发一个嵌入式 Linux 项目 一个工业应用程序 我有几个问题想问那些有嵌入式 Linux 经验的人 Y
  • 研究缓冲区溢出时应该使用哪些版本的 GCC 或标志?

    最近 作为计算机工程专业的本科生 我一直在研究缓冲区溢出 出于兴趣 我开始研究缓冲区溢出 但在尝试在我的计算机上用 GCC 4 9 1 在 Debian Jessie 中 编译的我自己的 C 程序中实现它们时遇到了困难 我听说较新的编译器中
  • 如何在文件中搜索多行模式?

    我需要找到包含特定字符串模式的所有文件 我想到的第一个解决方案是使用find管道与xargs grep find iname py xargs grep e YOUR PATTERN 但是 如果我需要查找跨越多行的模式 我就会陷入困境 因为
  • 如何在Linux中自动启动需要X的应用程序

    我试图在系统进入运行级别 5 时自动启动 X 应用程序 这样做的正确方法是什么 我写了一个脚本并将其放在 etc init d 中 我已运行适当的 chkconfig 命令来设置 etc rcX d 目录中的符号链接 一切工作正常 除了当我

随机推荐

  • 基于Unittest框架写的自动化脚本右键运行出现 run “py.test for ...“的解决办法

    一 看图 python脚本都是 unittest 写的 但是 运行的时候没注意是 py test 就运行了 二 网上找了解决办法 说是要修改默认运行方式 进入 File Settings Tools Python Integrated To
  • Git:更改远程仓库指向(五)

    修改已有git仓库的远程仓库指向 git remote set url origin 仓库地址 git remote set url origin git github com test thinkphp git Tips 小程序云开发 中
  • SpringBoot项目部署

    Springboot项目部署有两种方式 分别为 打包为jar war jar包和war包到部署服务器的区别和优缺点 1 部署war包 1 将war包解压 将里面的内容放到服务器项目的目录下 2 重启服务器 启动tomcat的时间会有些长 约
  • QNX系统BSP开发研发与应用,QNX技术解答-项目开发-软件开发

    如果你认为本系列文章对你有所帮助 请大家有钱的捧个钱场 点击此处赞助 赞助额0 1元起步 多少随意 声明 本文只用于个人学习交流 若不慎造成侵权 请及时联系我 立即予以改正 锋影 email 174176320 qq com 目前总结了一些
  • [LeetCode-27]-Remove Element (删除指定元素)

    文章目录 题目相关 Solution 题目相关 题目解读 使用In place 原地算法 从数组中删除指定值的所有元素 并返回删除后的数组长度 原题描述 原题链接 Given an array nums and a value val re
  • python函数式编程——迭代器(2)

    文章目录 前言 一 迭代器 前言 python学习笔记 仅供学习使用 一 迭代器 迭代是访问集合元素的 种 式 迭代器是 个可以记住遍历的位置的对象 迭代器对象从集合的第 个元素开始 访问 直到所有的元素被访问完结束 迭代器只能往前不会后退
  • java 静态变量 静态代码初始化块 构造函数的顺序

    静态变量或静态代码块 先后与代码书写顺序有关 初始化代码块或普通变量 顺序与代码书写顺序有关 构造函数 几大原则 一 静态成员变量 Static 1 静态成员变量为类变量 所有对象共享同一内存空间 2 静态成员变量的声明和定义仅在首次加载类
  • 视频无损放大软件:Topaz Video Enhance AI Mac版(支持m1)

    Topaz Video Enhance AI for Mac是一款专业的AI视频无损放大软件 topaz video enhance ai mac版使用时间信息有效提高视频质量和细节 从而达到最好的视频放大 去隔行 降噪和还原效果 另外to
  • gitlab目录功能结构

    默认安装的gitlab 主要有四个目录 opt gitlab 主目录 etc gitlab 放置配置文件 var opt gitlab 各个组件 var log gitlab 放置日志文件 功能操作 检查gitlab各组件状态 gitlab
  • 浅议代码安全检测

    2017年6月1日 中华人民共和国网络安全法 正式实施 等级保护工作正式入法 等级保护制度已成为新时期国家网络安全的基本国策和基本制度 2019年12月1日 网络安全等级保护条例 正式实施 等保2 0是从 信息安全等级保护制度 到 网络安全
  • 卸载vs2010亲测的一个方法

    最近想把vs2010卸载掉 把方法记录下 供需要的人参考 采用的方法是vs自带的卸载的方法 步骤如下 1 打开 控制面板 点击 卸载程序 在弹出的窗口里面找到vs2010的主程序 如图 2 双击打开后 或是右键弹出 卸载 更改 菜单 进入维
  • windows10环境下用anaconda和VScode配置

    文件下载 最新的Anaconda3 5 1 0 Windows x 64 exe版本中在安装的时候已经打包好了vscode 就是在anaconda3安装完成之后 会提示你是否要安装vscode 然后勾选就可以完成vscode的安装 Anac
  • vue实现消息提示框

    我们常常看到很多vue生态下的ui框架的消息提示框 在页面切换的时候依然停留在页面 我们知道vue这种单页面渐进式框架 所有的操作和元素都是挂载在一个节点上的 当路由变化是整个节点下的dom元素也在重新渲染 若要实现ui框架中的类似的消息提
  • 常用损失函数小结

    一 摘要 本文主要总结一下常见的损失函数 包括 MSE均方误差损失函数 SVM合页损失函数 Cross Entropy交叉熵损失函数 目标检测中常用的Smooth L1损失函数 其中还会涉及到梯度消失 梯度爆炸等问题 ESM均方误差 Sig
  • 【2017-07-04】Qt信号与槽深入理解之一:信号与槽的连接方式

    今天是个好日子 嗯 信号槽机制是Qt的特色功能之一 类似于windows中的消息机制 在不同的类对象间传递消息时我们经常使用信号槽机制 然而很多时候都没有去关注connect 函数到底有几种重载的形式 其中的各项参数都是什么 如果总是浮于表
  • Python opencv局部直方图均衡增强

    opencv直方图均衡包含两种 一种是对全图进行直方图均衡 另一种是对局部进行直方图均衡 也称为自适应直方图均衡 直方图均衡是让图像的像素分布更加均匀 一般可以使图片更亮 解决偏色问题 增加局部细节等 1 全局直方图均衡 全局直方图均衡的函
  • SpringBoot 中 Json 格式化配置

    SpringBoot 针对 jackson 是自动化配置的 如果需要修改 也可以自定义配置 0x01 通过 application yml 配置属性说明 spring jackson date format 指定日期格式 比如 yyyy M
  • 窗口函数之ntile()函数讲解

    ntile NTILE n 用于将分组数据按照顺序切分成n片 返回当前切片值 将一个有序的数据集划分为多个桶 bucket 并为每行分配一个适当的桶数 切片值 第几个切片 第几个分区等概念 它可用于将数据划分为相等的小切片 为每一行分配该小
  • WIN10 64位 OSG3.4+Qt5.3+VS2013 编译及使用dae插件、dxf插件

    OSG经过一段时间的发展 相比以前的开发来说 在编译安装上的步骤已经简单许多 但依旧存在许多的坑 本文简单阐述了在64位win10系统上 使用VS2013编译工具结合Qt5 3库 编译安装了带dae 3ds等3D显示插件的3 4版本的Ope
  • 标准IO及其各函数用法

    目录 综述标准IO与文件IO 1 fopen 函数 打开一个文件 2 fclose函数 关闭流 3 读写函数 3 1按字符读写 3 1 1 fgetc函数 从指定流中读取一个字符 3 1 2 fputc函数 向流中输出一个字符 3 1 3案