云计算百科
云计算领域专业知识百科平台

Linux标准IO与系统IO函数全解析

标准 IO 与系统 IO 函数整理(含参数、功能、区别)

本文档基于 Linux 标准 IO / 系统 IO 学习笔记,梳理所有涉及的函数,按标准 IO(文件操作 / 读写 / 定位 / 格式化)和系统 IO分类,明确每个函数的原型、参数、核心功能,并总结同类函数、标准 / 系统 IO 函数的核心区别。

一、标准 IO 函数(<stdio.h>)

标准 IO 是 C 标准库实现的文件操作接口,封装缓冲区,遵循 POSIX 标准,可跨平台使用,核心围绕FILE*文件流指针操作,Linux 下默认对普通文件全缓冲、标准输出行缓冲、标准错误无缓冲。

(一)文件基础操作(打开 / 关闭 / 刷新)

函数原型核心参数说明功能返回值关键备注
FILE *fopen(const char *pathname, const char *mode); pathname:文件路径 / 名;mode:打开模式(r/r+/w/w+/a/a+/rb/wb) 以指定模式打开文件,关联文件流 成功:FILE*文件流指针;失败:NULL 打开失败会设置errno,可通过perror打印;rb/wb为二进制模式,避免 Windows 换行符转换
int fclose(FILE *stream); stream:已打开的文件流指针 关闭文件流,刷新缓冲区,释放堆内存(FILE 结构体) 成功:0;失败:EOF(-1) 不可重复关闭,重复关闭会导致段错误(堆内存重复释放);关闭时自动刷新未写入的缓冲数据
int fflush(FILE *stream); stream:文件流指针(NULL 表示刷新所有输出流) 手动刷新缓冲区,将缓冲数据写入实际文件 成功:0;失败:EOF(-1) 仅对输出流 / 更新流有效;标准输出行缓冲下,\\n/ 程序结束 /fflush 都会触发刷新

(二)字符级读写(单字符操作)

函数原型核心参数说明功能返回值关键备注
int fgetc(FILE *stream); stream:待读取的文件流 从文件流读取一个字符,文件光标后移 1 字节 成功:字符 ASCII 码(unsigned char 转 int);失败 / 到末尾:EOF(-1) 可通过feof/ferror区分末尾和错误
int getc(FILE *stream); 同 fgetc 功能与 fgetc 完全一致 同 fgetc 实现为宏定义,可能多次计算stream,避免传入带副作用的表达式
int getchar(void); 无参数 从标准输入 stdin读取一个字符 同 fgetc 等价于getc(stdin)
int fputc(int c, FILE *stream); c:待写入字符的 ASCII 码;stream:目标文件流 向文件流写入一个字符,光标后移 1 字节 成功:写入的字符 ASCII 码;失败:EOF(-1) 追加模式(a/a+)下,始终写入文件末尾
int putc(int c, FILE *stream); 同 fputc 功能与 fputc 完全一致 同 fputc 实现为宏定义
int putchar(int c); c:待写入字符的 ASCII 码 向标准输出 stdout写入一个字符 同 fputc 等价于putc(c, stdout)

(三)行级读写(按行操作)

函数原型核心参数说明功能返回值关键备注
char *fgets(char *s, int n, FILE *stream); s:存储数据的缓冲区;n:缓冲区大小;stream:待读取文件流 从文件流读取一行数据,最多读n-1个字符(留 1 位存\\0),遇\\n/EOF/ 满缓冲区停止,保留\\n 成功:缓冲区指针s;失败 / 到末尾且无数据:NULL 可通过feof/ferror区分末尾和错误;解决了gets的缓冲区溢出问题
int fputs(const char *s, FILE *stream); s:待写入的字符串;stream:目标文件流 向文件流写入字符串,不写入末尾的\\0 成功:非负整数;失败:EOF(-1) 不会自动添加\\n,需手动在字符串中加入
int puts(const char *s); s:待写入的字符串 向标准输出 stdout写入字符串,自动添加\\n 成功:非负整数;失败:EOF(-1) 等价于fputs(s, stdout) + putchar('\\n')

(四)块级读写(按数据块操作,高效)

函数原型核心参数说明功能返回值关键备注
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); ptr:存储数据的缓冲区;size:单个数据块的字节数;nmemb:要读取的块数;stream:待读取文件流 从文件流读取nmemb 个 size 字节的块,总读取字节数 = size×nmemb 成功:实际读取的块数;失败 / 到末尾:小于 nmemb 或 0 二进制模式下使用更高效;返回值 < nmemb 时,需feof(stream)判断是否到末尾,ferror(stream)判断是否出错
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); ptr:待写入数据的缓冲区;其余同 fread 向文件流写入nmemb 个 size 字节的块,总写入字节数 = size×nmemb 成功:实际写入的块数;失败:小于 nmemb 或 0 二进制模式下可拷贝任意文件(文本 / 图片 / 视频);写入失败仅因 IO 错误,无 “到末尾” 情况

(五)文件定位(光标 / 偏移量操作)

函数原型核心参数说明功能返回值关键备注
int fseek(FILE *stream, long offset, int whence); stream:文件流;offset:偏移量(可正可负);whence:基准点(SEEK_SET / 开头、SEEK_CUR / 当前、SEEK_END / 末尾) 设置文件流的光标偏移量 成功:0;失败:非 0 二进制文件:offset 可任意设置;文本文件:offset 只能为 0 或 ftell 返回值,且 whence 为 SEEK_SET
long int ftell(FILE *stream); stream:文件流 获取当前光标相对于文件开头的偏移量(字节数) 成功:偏移量(长整型);失败:-1L 结合fseek(fp, 0, SEEK_END)可快速获取文件大小
void rewind(FILE *stream); stream:文件流 将光标重置到文件开头,同时清除文件的错误 / 结束标志 无返回值 等价于fseek(stream, 0L, SEEK_SET) + clearerr(stream)

(六)错误 / 结束判断

函数原型核心参数说明功能返回值关键备注
int feof(FILE *stream); stream:文件流 判断文件流是否到达末尾(EOF) 是:非 0 值;否:0 仅在读操作后判断才有意义,未读操作时默认返回 0
int ferror(FILE *stream); stream:文件流 判断文件流是否发生读写错误 是:非 0 值;否:0 错误标志需通过clearerr清除
void clearerr(FILE *stream); stream:文件流 清除文件流的结束标志(feof)和错误标志(ferror) 无返回值 重置后可重新判断文件状态

(七)格式化读写(按指定格式输入输出)

函数原型核心参数说明功能返回值关键备注
int fprintf(FILE *stream, const char *format, …); stream:目标文件流;format:格式化字符串;…:可变参数 向指定文件流写入格式化数据 成功:写入的字符数;失败:EOF(-1) 标准输出版为printf,等价于fprintf(stdout, format, …)
int fscanf(FILE *stream, const char *format, …); stream:待读取文件流;其余同 fprintf 从指定文件流读取格式化数据到变量 成功:成功匹配的参数个数;失败 / 到末尾:EOF(-1) 标准输入版为scanf,等价于fscanf(stdin, format, …);会自动跳过空白符(空格 / 换行 / Tab)
int sprintf(char *s, const char *format, …); s:存储格式化数据的缓冲区;其余同 fprintf 向内存缓冲区写入格式化数据,自动添加\\0 成功:写入的字符数(不含\\0);失败:负数 存在缓冲区溢出风险,推荐使用snprintf
int snprintf(char *s, size_t n, const char *format, …); n:缓冲区最大字节数;其余同 sprintf 向缓冲区写入格式化数据,最多写 n-1 个字符,自动加\\0 成功:预期写入的字符数;失败:负数 安全版 sprintf,避免缓冲区溢出;若返回值 >=n,说明数据被截断

二、系统 IO 函数(Linux 内核提供,无缓冲区)

系统 IO 是 Linux 内核直接提供的文件操作接口,无封装缓冲区,基于 ** 文件描述符(fd,非负整数)** 操作,仅适用于 Linux/Unix 系统,可操作所有类型文件(普通文件 / 设备 / 套接字 / 链接),实时性高,适合硬件设备交互。

(一)文件基础操作(打开 / 关闭)

函数原型 核心参数说明 功能 返回值 关键备注
int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode); pathname:文件路径 / 名;flags:打开标志(O_RDONLY/O_WRONLY/O_RDWR/O_CREAT/O_TRUNC/O_APPEND);mode:文件权限(八进制,如 0644,仅 O_CREAT 时有效) 打开 / 创建文件,分配文件描述符 成功:未使用的最小非负整数(fd);失败:-1
int close(int fd); fd:文件描述符 关闭文件描述符,释放内核文件资源 文件资源成功:0;失败:-1

(二)块级读写(仅支持数据块操作)

函数原型核心参数说明功能返回值关键备注
ssize_t read(int fd, void *buf, size_t count); fd:文件描述符;buf:存储数据的缓冲区;count:期望读取的最大字节数 从 fd 指向的文件读取最多 count 字节到缓冲区 成功:实际读取的字节数;失败:-1;到末尾:0 无缓冲区,每次调用都是系统调用;读取普通文件时,返回值 < count 即到末尾
ssize_t write(int fd, const void *buf, size_t count); fd:文件描述符;buf:待写入数据的缓冲区;count:期望写入的字节数 向 fd 指向的文件写入最多 count 字节从缓冲区 成功:实际写入的字节数;失败:-1 追加模式(O_APPEND)下,写入前自动将偏移量移到文件末尾;写入磁盘时可能因磁盘满导致返回值 < count

(三)文件定位(偏移量操作)

函数原型核心参数说明功能返回值关键备注
off_t lseek(int fd, off_t offset, int whence); fd:文件描述符;offset:偏移量(可正可负);whence:基准点(SEEK_SET/SEEK_CUR/SEEK_END,同 fseek) 设置文件描述符的偏移量 成功:新偏移量(相对于文件开头的字节数);失败:(off_t)-1 可通过lseek(fd, 0, SEEK_END)快速获取文件大小;支持将偏移量设为文件末尾之后(形成 “文件空洞”)

(四)时间函数(辅助作业,<time.h>)

函数原型核心参数说明功能返回值关键备注
time_t time(time_t *tloc); tloc:存储时间的指针(一般传 NULL) 获取从1970-01-01 00:00:00 UTC到当前的秒数(时间戳) 成功:时间戳(time_t 为长整型);失败:(time_t)-1 需结合localtime/strftime转换为本地时间和指定格式

三、核心区别总结

(一)同类标准 IO 函数的区别

  • fgetc/getc/getchar:功能一致,fgetc 是函数,getc 是宏,getchar 是针对 stdin 的封装;
  • fputc/putc/putchar:功能一致,fputc 是函数,putc 是宏,putchar 是针对 stdout 的封装;
  • fgets/gets:fgets 安全(指定缓冲区大小),保留\\n;gets 存在缓冲区溢出,已被废弃;
  • fputs/puts:fputs 不自动加\\n,可指定文件流;puts 自动加\\n,仅输出到 stdout;
  • sprintf/snprintf:snprintf 是安全版,指定缓冲区大小,避免溢出;sprintf 无大小限制,易溢出;
  • printf/fprintf:printf 是 fprintf 针对 stdout 的封装,fprintf 可指定任意文件流。

(二)标准 IO 与系统 IO 的核心区别

对比维度标准 IO(C 库)系统 IO(Linux 内核)
操作句柄 FILE*文件流指针(结构体,封装 fd 和缓冲区) 文件描述符fd(非负整数,内核 fd_array 数组下标)
缓冲区 封装用户态缓冲区(全缓冲 / 行缓冲 / 无缓冲),减少系统调用 无用户态缓冲区,每次操作都是直接系统调用
跨平台性 遵循 POSIX/ANSI C 标准,可在 Linux/Windows 等跨平台使用 仅适用于 Linux/Unix 类系统,与内核强绑定
支持文件类型 仅适用于普通文件 / 标准输入输出 支持所有 Linux 文件类型(普通 / 设备 / 套接字 / 链接 / 管道)
效率 普通文件操作效率高(缓冲区减少系统调用) 普通文件操作效率低(频繁系统调用),但硬件设备实时性高
内存管理 fopen 申请堆内存(FILE 结构体),fclose 释放,重复关闭段错误 open/close 无堆内存操作,仅操作内核资源,重复关闭无错误
函数丰富度 函数丰富(字符 / 行 / 块 / 格式化读写,定位 / 刷新 / 错误判断) 函数简洁(仅块读写 / 定位 / 打开关闭),无格式化 / 字符 / 行操作
头文件 核心 <**stdio.h**>,时间函数 <time.h> 核心 <**unistd.h**>、<sys/types.h>、<fcntl.h>

(三)fread/fwrite 与 read/write 的关键区别

  • 返回值:fread/fwrite 返回实际操作的块数,read/write 返回实际操作的字节数;
  • 错误判断:fread/fwrite 返回值 < 指定值时,需feof/ferror区分末尾 / 错误;read/write 返回 – 1 为错误,0 为末尾;
  • 缓冲区:fread/fwrite 基于用户态缓冲区,底层调用 read/write;read/write 无缓冲区,直接操作内核;
  • 跨平台:fread/fwrite 可跨平台,read/write 仅 Linux/Unix 可用。

(四)fseek/ftell 与 lseek 的关键区别

  • 操作句柄:fseek/ftell 操作FILE*,lseek 操作fd;
  • 参数 / 返回值类型:fseek 的 offset 是long,ftell 返回long int;lseek 的 offset 是off_t,返回off_t(64 位系统支持更大偏移);
  • 文本文件限制:fseek 对文本文件偏移量有限制(仅 0/ftell 返回值);lseek 对文本 / 二进制文件无限制;
  • 文件空洞:lseek 支持将偏移量设为文件末尾之后,形成 “文件空洞”;fseek 不推荐此操作。
赞(0)
未经允许不得转载:网硕互联帮助中心 » Linux标准IO与系统IO函数全解析
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!