一 .文件IO系列
第一组:文件属性获取(stat / fstat / lstat)
头文件:#include <sys/stat.h> #include <unistd.h>
1. int stat(const char *pathname, struct stat *statbuf);
-
功能:通过文件路径获取文件属性,会追踪软链接(指向源文件)。
-
参数:
-
pathname:字符串,要查询的文件路径(如 "./test.txt")。
-
statbuf:输出型参数,指向 struct stat 结构体的指针。内核会把文件大小、权限、时间等信息填充到这个结构体中。
-
-
返回值:成功返回 0,失败返回 -1(并设置 errno)。
2. int fstat(int fd, struct stat *statbuf);
-
功能:通过文件描述符获取文件属性(无需路径)。
-
参数:
-
fd:已打开的文件描述符(由 open 返回)。
-
statbuf:同上,输出型参数。
-
-
返回值:成功返回 0,失败返回 -1。
3. int lstat(const char *pathname, struct stat *statbuf);
-
功能:通过文件路径获取文件属性,不会追踪软链接(查的是链接文件本身,不是它指向的目标)。
-
参数:同 stat。
-
返回值:成功返回 0,失败返回 -1。
第二组:目录流操作(opendir / readdir / closedir)
头文件:#include <dirent.h>
4. DIR *opendir(const char *name);
-
功能:打开一个目录,建立目录流(相当于针对目录的 open)。
-
参数:
-
name:目录路径字符串(如 "." 当前目录,"/home")。
-
-
返回值:成功返回目录流指针 DIR*,失败返回 NULL(并设置 errno)。
5. struct dirent *readdir(DIR *dirp);
-
功能:从已打开的目录流中,逐条读取下一个目录项(一个文件或子目录)。
-
参数:
-
dirp:由 opendir 返回的目录流指针。
-
-
返回值:成功返回指向 struct dirent 结构体的指针(该结构体里有文件名 d_name),读到末尾或出错时返回 NULL(用 errno 区分是结束还是出错)。
-
重要细节:每调用一次,自动往后移一个条目。
6. int closedir(DIR *dirp);
-
功能:关闭目录流,释放相关资源。
-
参数:dirp:要关闭的目录流指针。
-
返回值:成功返回 0,失败返回 -1。
第三组:文件描述符复制(dup / dup2)
头文件:#include <unistd.h>
7. int dup(int oldfd);
-
功能:复制一个文件描述符。新描述符指向内核中同一个文件对象(共享偏移量和锁)。
-
参数:
-
oldfd:要被复制的旧文件描述符。
-
-
返回值:成功返回新的文件描述符(系统自动分配当前最小的可用数字),失败返回 -1。
8. int dup2(int oldfd, int newfd);
-
功能:复制 oldfd,但强制把 newfd 作为新的副本编号。如果 newfd 已被打开,内核会先静默关闭它,再让它指向 oldfd 的文件对象。
-
参数:
-
oldfd:旧文件描述符。
-
newfd:你指定的新文件描述符编号(如 1)。
-
-
返回值:成功返回 newfd,失败返回 -1。
第四组:文件控制万能锁(fcntl)
头文件:#include <fcntl.h> #include <unistd.h>
9. int fcntl(int fd, int cmd, … /* arg */);
-
功能:对已打开的文件描述符执行各种控制操作(修改标志、复制 fd、加锁等)。这是一个可变参数函数。
-
参数:
-
fd:要操作的文件描述符。
-
cmd:操作命令(必填),常见取值:
-
F_GETFL:获取文件状态标志(如是否阻塞)。此时不需要第三个参数。
-
F_SETFL:设置文件状态标志。此时第三个参数 arg 必须传入新的标志(如 O_NONBLOCK)。
-
F_DUPFD:复制 fd,此时第三个参数 arg 指定新 fd 的最小可用数字(类似 dup 的加强版)。
-
F_SETLK / F_SETLKW:设置记录锁,此时第三个参数必须是 struct flock* 指针。
-
-
…:arg(可选),取决于 cmd。
-
-
返回值:取决于 cmd:
-
F_GETFL 成功返回标志值(整数);
-
其他命令成功返回 0;
-
统一失败返回 -1。
-
第五组:删除目录项(unlink)
头文件:#include <unistd.h>
10. int unlink(const char *pathname);
-
功能:从文件系统中删除一个名字(目录项)。当文件的硬链接数减为 0 且没有进程打开它时,磁盘空间才会被释放(这是 rm 命令的底层实现)。
-
参数:
-
pathname:要删除的文件路径字符串。
-
-
返回值:成功返回 0,失败返回 -1。
第六组:检查文件权限(access)
头文件:#include <unistd.h>
11. int access(const char *pathname, int mode);
-
功能:以调用进程的真实用户 ID 和组 ID 来检查对文件的访问权限(常用于在真正 open 前做预判)。
-
参数:
-
pathname:文件路径。
-
mode:要检查的权限位(只能传以下宏之一):
-
F_OK:检查文件是否存在。
-
R_OK:检查是否可读。
-
W_OK:检查是否可写。
-
X_OK:检查是否可执行。
-
-
-
返回值:允许(满足权限)返回 0,拒绝(不满足)或出错返回 -1。
第七组:截断/扩展文件大小(truncate / ftruncate)
头文件:#include <unistd.h> #include <sys/types.h>
12. int truncate(const char *path, off_t length);
-
功能:通过文件路径将文件大小设置为 length 字节。如果原文件大于 length,尾部被丢弃;小于 length,文件被扩展(中间会形成“空洞”,不占物理磁盘空间)。
-
参数:
-
path:文件路径字符串。
-
length:目标长度(字节数,off_t 类型)。
-
-
返回值:成功返回 0,失败返回 -1。
13. int ftruncate(int fd, off_t length);
-
功能:通过文件描述符将文件大小设置为 length 字节(功能同 truncate,但操作的是已打开的文件)。
-
注意:该文件必须以可写方式打开(O_WRONLY 或 O_RDWR)。
-
参数:
-
fd:已打开的文件描述符。
-
length:目标长度。
-
-
返回值:成功返回 0,失败返回 -1。
二 . 标准IO系列
第一组:状态判断(feof / ferror / clearerr)
头文件:#include <stdio.h>
1. int feof(FILE *stream);
-
作用:检查文件流是否到达了文件末尾。
-
参数:stream —— 文件流指针。
-
返回值:如果已到达文件末尾,返回非零值(真);否则返回 0(假)。
-
陷阱:feof 不会在刚读完最后一个字符时返回真,而是在你尝试越过末尾再读一次后才会返回真。所以千万不要用它来做循环终止条件(正确姿势是 while(fread(…) > 0),循环结束后再判断 feof)。
2. int ferror(FILE *stream);
-
作用:检查文件流是否发生了 I/O 错误。
-
参数:stream —— 文件流指针。
-
返回值:如果发生了错误,返回非零值(真);否则返回 0(假)。
-
场景:当 fread 或 fgetc 返回异常值时,用 ferror 区分“读到末尾”和“读取出错”。
3. void clearerr(FILE *stream);
-
作用:清除文件流的文件结束标志(EOF)和错误标志。
-
参数:stream —— 文件流指针。
-
返回值:无(void)。
-
场景:当你处理完一个错误,或者用 rewind 重置位置后,需要手动清除标志,否则后续的读写操作会被阻塞。
第二组:大文件位置控制(fgetpos / fsetpos)
头文件:#include <stdio.h>
4. int fgetpos(FILE *stream, fpos_t *pos);
-
作用:获取当前文件流的位置指示器,存入 pos 结构体中(支持超大文件 >2GB)。
-
参数:
-
stream:文件流指针。
-
pos:输出型参数,指向 fpos_t 类型变量的指针,用来接收位置值。
-
-
返回值:成功返回 0,失败返回 非零值(并设置 errno)。
5. int fsetpos(FILE *stream, const fpos_t *pos);
-
作用:将文件流的位置指示器设置到 pos 指定的位置(通常与 fgetpos 配合使用)。
-
参数:
-
stream:文件流指针。
-
pos:输入型参数,指向之前用 fgetpos 获取的 fpos_t 值。
-
-
返回值:成功返回 0,失败返回 非零值。
-
与 fseek 的区别:fpos_t 可以存储复杂的文件状态,在超大文件(>2GB)和特殊文件系统上表现更安全。
第三组:缓冲区强制刷新(fflush)
头文件:#include <stdio.h>
6. int fflush(FILE *stream);
-
作用:强制将用户态缓冲区中未写入的数据刷入内核(调用 write)。
-
参数:
-
stream:文件流指针。如果传 NULL,则刷新所有已打开的流的输出缓冲区。
-
-
返回值:成功返回 0,失败返回 EOF(并设置 errno)。
-
注意:fflush 只保证数据到达内核页缓存,不保证落盘。想落盘需调用 fsync(fileno(fp))。
第四组:(fileno / fdopen)
头文件:#include <stdio.h> (在 Linux 下,fileno 和 fdopen 也依赖 <unistd.h> 和 <fcntl.h>)
7. int fileno(FILE *stream);
-
作用:从标准I/O流(FILE*)中,掏出底层的文件描述符(fd)。
-
参数:stream —— 文件流指针。
-
返回值:成功返回底层的 int fd,失败返回 -1。
-
场景:当你用 fopen 打开了文件,但突然想用 fcntl 加锁,或者用 fsync 强制落盘时,必须靠它取出 fd。
8. FILE *fdopen(int fd, const char *mode);
-
作用:将一个已有的文件描述符(fd),包装成一个标准I/O流(FILE*)。
-
参数:
-
fd:已打开的文件描述符(来自 open 或 socket)。
-
mode:字符串,和 fopen 一样(如 "r"、"w+")。必须与 fd 打开时的模式兼容(比如 fd 是只读的,就不能传 "w")。
-
-
返回值:成功返回 FILE* 指针,失败返回 NULL。
-
场景:网络编程中,你从 socket() 拿到了 fd,但想用 fprintf 格式化输出数据,就可以用它包装。
第五组:安全字符串格式化(snprintf / sscanf)
头文件:#include <stdio.h>
9. int snprintf(char *str, size_t size, const char *format, …);
-
作用:将格式化数据写入字符串,并保证不超过指定长度,末尾自动添加 '\\0'(防止缓冲区溢出)。
-
参数:
-
str:目标字符串缓冲区。
-
size:缓冲区的最大长度(包含结尾的 '\\0')。
-
format:格式化字符串(同 printf)。
-
…:可变参数列表。
-
-
返回值:如果缓冲区足够大,返回本应写入的字符数(不包括结尾的 '\\0');如果返回值 >= size,说明数据被截断了。
-
铁律:永远用 snprintf 替代不安全的 sprintf!
10. int sscanf(const char *str, const char *format, …);
-
作用:从字符串 str 中,按照 format 格式提取数据,存入后面的变量中。
-
参数:
-
str:源字符串(通常来自 fgets 读的一行)。
-
format:格式字符串(同 scanf)。
-
…:目标变量的地址(带 &)。
-
-
返回值:成功匹配并赋值的参数个数(可用于校验读取是否成功)。如果返回 0 或 EOF,说明格式不匹配。
-
工程组合:fgets 读一行 + sscanf 解析 => 最安全的配置文件/CSV 读取方式,避免 fscanf 直接操作文件流可能导致的卡死或位置错乱。





