目录

序言

一、概述

标准 I/O 是 C 标准库为我们提供的一套API接口,用户可以根据标准输入输出头文件<stdio.h>中的函数声明进行调用,Linux系统下该头文件路径为 /user/include
在C99标准手册可查看--C Standard C99-->Library-->7.19 Input/Output<stdio.h>

二、文件流(FILE)

FILE 在 Linux 系统的标准 IO 库中是用于描述文件的结构,称为文件流。
标准IO默认打开了三个流,stdin(标准输入)、stdout(标准输出)、stderr(标准错误)

FILE类型其实是一个结构体数据类型,它包含了标准 I/O 库函数为管理文件所需要的所有信息,比如包括用于实际I/O 的文件描述符、指向文件缓冲区的指针、缓冲区的长度、当前缓冲区中的字节数以及出错标志等。
FILE 结构在程序执行 fopen 函数时会进行创建,并分配在堆内存中。我们常定义一个指向 FILE 结构的指针(文件指针)来接收这个返回值。

头文件stdio.h中有关于FILE类型的相关描述,如:

标准IO-小白菜博客
image-20250811221651290

三、标准 I/O 的缓冲机制

标准I/O可以看成是在系统I/O的基础上封装了缓冲机制

image-20260623165906554

根据IO设备的不同,通常将缓冲区分为输入缓冲区输出缓冲区,同样,根据刷新形式的不同,可以把缓冲区分为三种:全缓冲、行缓冲、无缓冲

全缓冲:一般读写文件的时候会采用

  • 程序正常终止
  • 调用fflush函数
  • 缓冲区被填满
  • 关闭文件、读取文件内容以及修改缓冲区类型时

行缓冲:一般操作IO设备时会采用,比如printf函数就是采用行缓冲

  • 程序正常终止
  • 调用fflush函数
  • 缓冲区被填满(一般缓冲区为4KB,就是4096字节)
  • 缓冲区中遇到换行符’\n’时,
  • 在关闭文件、读取文件内容以及修改缓冲区类型时

无缓冲:指的是没有缓冲区,每次I/O操作立即通过系统调用写入内核,一般linux系统的标准出错stderr就是采用无缓冲, 这样可以把错误信息直接输出。

注意:对于标准输出stdout而言默认是采用行缓冲的,而对于标准出错stderr而言默认是采用无缓冲的,对于普通文件而言默认是采用全缓冲的。

标准IO的常用API接口

一、打开文件 fopen

功能:以文件流的方式打开文件
函数原型:
FILE *fopen(const char *pathname, const char *mode);
参数分析:
@ pathname  :	待打开的文件的路径,如字符串"demo.txt"
@ mode		:	访问文件的权限
				r  	--> 打开文本以供读取,默认指向文件头。
            	r+	-->	打开文本以供读取/写入,默认指向文件头。
            	w	-->	打开文本以供写入,默认指向文件头,如果文件不存在则创建,如果存在则清空。
            	w+	-->	打开文本以供读取/写入,默认指向文件头,如果文件不存在则创建,如果存在则清空。
            	a	-->	打开文本以供追加(在文本末尾写入),默认指向文件尾部,如果不存在则创建,如果存在则追加。
            	a+	-->	打开文本以供读取/追加(在文本末尾写入),默认指向文件尾部,如果不存在则创建,如果存在则追加。
返回值:
    	成功 返回指向文件的FILE指针
    	失败 返回NULL 并设置错误码
备注:	无

二、关闭文件 fclose

功能:关闭文件流
函数原型:
FILE *fclose(FILE *stream);
参数分析:
@ stream  :	指向想要关闭文件的FILE指针
返回值:
    	成功 返回0
    	失败 返回EOF	EOF是文件结束标志,其实是个宏定义,宏定义的值为 -1,在头文件libio.h中有相关描述。
备注:	使用标准IO的时候,不可以反复使用fclose关闭相同的文件,因为释放已经被释放的堆内存,会导致段错误!!

三、读取数据

1.字符读取

功能:获取指定文件的一个字符
函数原型:
int fgetc(FILE *stream);
int getc(FILE *stream);
int getchar(void);
参数分析:
@ stream  :	待读取数据的文件指针
返回值:
    	成功 返回读取到的字符
    	失败 返回EOF	(当返回EOF时,文件 stream可能已达末尾,或者遇到错误)
备注:	fgetc()与 getc()功能完全一样,区别是getc()函数的实现是利用宏定义
	  getcahr()缺省从标准输入stdin中读取字符

2.按行读取

功能:从指定的文件中读取一行字符,并把读取的字符存储在指针s所指向的字符串内
函数原型:
int fgets(char * restrict s, int n, FILE * restrict stream);
int gets(char *s);
参数分析:
@ s		  : 自定义缓冲区指针
@ n	  	  : 要读取的最大字符数(包括最后的空字符)
@ stream  :	待读取数据的文件指针
返回值:
    	成功 返回自定义缓冲区指针s
    	失败 返回NULL	(当返回NULL时,文件 stream可能已达末尾,或者遇到错误)
备注:	当读取到n-1个字符、或者已经读取到文件末尾(EOF)、或者读取到换行符’\n’时,则函数调用停止
	  gets()缺省从标注输入stdin中读取数据

3.按块读取 fread

功能:从指定的文件读取若干个数据块
函数原型:
size_t fread(void * restrict ptr, size_t size, size_t nmenb, FILE * restrict stream); 
参数分析:
@ ptr	  : 自定义缓冲区指针
@ size	  : 要读取的数据块大小
@ nmemb	  :	要读取的数据块数量
@ stream  :	待读取数据的文件指针
返回值:
    	成功 返回读取的数据块个数,等于nmemb
    	失败 返回读取的数据块格式,小于nmemb或等于0
备注:	当返回小于nmemb时,文件 stream可能已达末尾,或者遇到错误
      可以通过标准库中提供的两个函数区分是读取错误还是到达文件末尾,一个函数是 feof,另一个则是 ferror函数。

四、写入数据

1.字符写入

功能:将一个字符写入一个指定的文件
函数原型:
int fputc(int c, FILE *stream);
int putc(int c, FILE *stream);
int putchar(int c);
参数分析:
@ c		  : 待写入的字符
@ stream  :	待写入数据的文件指针
返回值:
    	成功 返回写入到的字符
    	失败 返回EOF
备注:	fputc()与 putc()功能完全一样,区别是putc()函数的实现是利用宏定义
	  putchar()缺省将数据写入标注输出stdout

2.按行写入

功能:将数据写入指定的文件
函数原型:
int fputs(char * restrict s, FILE * restrict stream);
int puts(char *s);
参数分析:
@ s		  : 自定义缓冲区指针
@ stream  :	待写入数据的文件指针
返回值:
    	成功 返回非负整数
    	失败 返回EOF
备注:	字符串的结束符未被写入到文件中
	  puts()缺省将数据写入标注输出stdout

3.按块写入 fwrite

功能:读取若干个数据块写入到指定的文件
函数原型:
size_t fwrite(const void * restrict ptr, size_t size, size_t nmenb, FILE * restrict stream); 
参数分析:
@ ptr	  : 自定义缓冲区指针
@ size	  : 要写入的数据块大小
@ nmemb	  :	要写入的数据块数量
@ stream  :	待写入数据的文件指针
返回值:
    	成功 返回写入的数据块个数,等于nmemb
    	失败 返回写入的数据块格式,小于nmemb或等于0
备注:	无

五、文件位置

每个被打开文件的结构体中都有一个位置指示器(简单理解:位置指示器是文件光标),注意:被打开的文件的光标默认是在文件开头的。

1.设置位移 fseek

功能:设置文件光标的偏移量
函数原型:
int fseek(FILE * stream, long int offset, int whence); 
参数分析:
@ stream  :	需要设置位置偏移量的文件指针
@ offset  : 新位置偏移量相对基准点的偏移
@ whence  : 基准点	: 
    				SEEK_SET -->文件开头处
    				SEEK_CUR -->当前位置
    				SEEK_END -->文件末尾处
返回值:
    	成功 返回0
    	失败 返回-1
备注:	无

2.获取位移 ftell

功能:获取指定的文件的当前位置偏移量
函数原型:
int ftell(FILE * stream); 
参数分析:
@ stream  :	需要返回当前文件位置偏移量的文件指针
返回值:
    	成功 返回文件的位置指示器的当前值
    	失败 返回-1
备注:	无

其他标准IO接口

文件访问

1.刷新缓冲区 fflush

功能:刷新输出缓冲区
函数原型:
int fflush(FILE * stream); 
参数分析:
@ stream  :	需要刷新缓冲区的文件指针	(如果 stream 为 NULL,则会刷新所有输出流的缓冲区)
返回值:
    	成功 返回0
    	失败 返回EOF 且设置错误标识符
备注:	无

格式访问

1.fprintf

功能:向指定的文件中输出格式化字符串
函数原型:
int fprintf(FILE * restrict stream, const char * restrict format, ...); 
参数分析:
@ stream  :	待写入格式化字符串的文件指针
@ format  : 格式化字符串的格式--(与printf相同)
返回值:
    	成功 返回写入的字符总数
    	失败 返回一个负数
备注:	无

2.sprintf

功能:向指定的字符数组输出格式化字符串
函数原型:
int sprintf(char * restrict s, const char * restrict format, ...); 
参数分析:
@ s  	  :	待写入格式化字符串的指向一个字符数组的指针
@ format  : 格式化字符串的格式--(与printf相同)
返回值:
    	成功 返回写入的字符总数,不包括字符串追加在字符串末尾的空字符
    	失败 返回一个负数
备注:	无

错误处理

1.feof

功能:检测文件是否已经读到末尾
函数原型:
int feof(FILE * stream); 
参数分析:
@ stream  :	需要检测的文件指针
返回值:
    	成功 返回非零值,即到达文件末尾
    	失败 返回0
备注:	无

2.ferror

功能:检查流(stream)的错误指示符
函数原型:
int ferror(FILE * stream); 
参数分析:
@ stream  :	需要检查的文件指针
返回值:
    	成功 返回非零值,表示发生错误
    	失败 返回0
备注:	无

参考链接

Linux 文件 I/O 与标准 I/O 缓冲机制详解 - 知乎

FILE结构 - CTF Wiki

C 标准库 – | 菜鸟教程