标准IO及其各函数用法

目录

综述标准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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

翔在天上飞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值