一、缓冲区与标准 I/O
缓冲区设计原则
- 终端关联:设计行缓存
- 普通文件:全缓存
- 出错输出:不缓存
缓冲区在实际发生 I/O 操作时才真正开辟。
行缓存(1024 字节)
刷新条件:
- 遇到
\n - 程序正常结束
- 缓冲区满
fflush强制刷新
全缓存(4096 字节)
刷新条件:
- 程序正常结束
- 缓冲区满
fflush强制刷新
不缓存
没有缓存,大小为 0。
输出重定向
./a.out > 1.txt # 输出重定向
./a.out < 1.txt # 输入重定向
二、标准 I/O 与文件 I/O
标准 I/O(库函数)
-
核心概念
- 抽象一个流(
FILE *) - 设计缓存
- 封装底层的文件描述符
- 抽象一个流(
文件 I/O(系统调用,不带缓冲的 I/O)
1.打开文件:open
#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
- 必选项:
O_RDONLY(只读)、O_WRONLY(只写)、O_RDWR(读写) - 可选项:
O_APPEND(追加)、O_CREAT(文件不存在则创建)、O_TRUNC(截断为 0) - 返回值:成功返回新的文件描述符;失败返回 -1 并设置
errno
fopen 与 open 的对应关系:
fopen("1.txt", "r") <==> open("1.txt", O_RDONLY);
fopen("1.txt", "r+") <==> open("1.txt", O_RDWR);
fopen("1.txt", "w") <==> open("1.txt", O_WRONLY|O_TRUNC|O_CREAT, 0666);
fopen("1.txt", "w+") <==> open("1.txt", O_RDWR|O_TRUNC|O_CREAT, 0666);
fopen("1.txt", "a") <==> open("1.txt", O_WRONLY|O_APPEND|O_CREAT, 0666);
fopen("1.txt", "a+") <==> open("1.txt", O_RDWR|O_APPEND|O_CREAT, 0666);
2.关闭文件:close
int close(int fd);
- 功能:关闭文件描述符,关闭后该文件描述符可被重复使用
- 返回值:成功返回 0;失败返回 -1
- 文件描述符分配原则:最小未使用
3.读写操作:read / write
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
read:从fd中读取count个字节到buf,成功返回读取到的字节数,读到末尾返回 0write:将buf中count个字节写入fd,成功返回写入的字节数
4.文件定位:lseek
off_t lseek(int fd, off_t offset, int whence);
whence参考点:SEEK_SET(文件开头)、SEEK_CUR(当前位置)、SEEK_END(文件末尾)- 常用操作:
lseek(fd, 0, SEEK_SET); // 定位到文件开头 off_t len = lseek(fd, 0, SEEK_END); // 获取文件大小空洞文件:先定位再写入,可创建空洞文件
lseek(fd, 100-1, SEEK_SET); write(fd, "", 1);标准 I/O vs 文件 I/O
类型 特点 标准 I/O 库函数,功能丰富、使用方便、可移植性好,需注意缓存与安全性 文件 I/O 系统调用,函数简单,复杂功能需自行封装,可移植性差,安全性较好 三、混合使用与目录操作
混合使用
可以在标准 I/O 和文件 I/O 之间转换:
FILE *fdopen(int fd, const char *mode); // 把文件描述符 fd 转换为 FILE* int fileno(FILE *stream); // 把 FILE* 转换为文件描述符 fd目录文件操作打开目录:
1.打开目录:opendir
#include <dirent.h>
DIR *opendir(const char *name);
- 功能:打开目录并创建目录流
- 返回值:成功返回目录流指针;失败返回 NULL 并设置
errno
2.读取目录项:readdir
struct dirent *readdir(DIR *dirp);
- 功能:读取目录项
struct dirent结构:struct dirent { ino_t d_ino; // Inode 编号 off_t d_off; // 偏移量 unsigned short d_reclen; // 记录长度 unsigned char d_type; // 文件类型 char d_name[256]; // 文件名(以 '\0' 结尾) };4.关闭目录:
closedirint closedir(DIR *dirp);功能:关闭目录流


被折叠的 条评论
为什么被折叠?



