文件I/O和目录操作
一、系统调用与C库函数
1. 系统调用 (File I/O)
操作系统提供的底层接口
直接访问内核功能
功能强大,但平台相关
对设备文件操作更高效
2. C库函数 (Standard I/O)
C标准库提供的高级接口
跨平台,通用性好
带缓冲机制,适合非设备文件
底层调用系统调用函数
二、文件操作对比
| 特性 | 标准I/O | 文件I/O |
|---|---|---|
| 接口类型 | C库函数 | 系统调用 |
| 文件标识 | FILE* 文件流指针 | int 文件描述符 |
| 缓冲机制 | 带缓冲区 | 无缓冲区 |
| 移植性 | 高(跨平台) | 低(平台相关) |
| 适合场景 | 普通文件 | 设备文件 |
三、文件I/O操作步骤
1. 打开文件 -open()
#include <fcntl.h> #include <unistd.h> int open(const char *pathname, int flags, int mode);
功能: 获得一个文件描述符
参数:
pathname: 文件名flags:O_RDONLY: 只读O_WRONLY: 只写O_RDWR: 读写O_CREAT: 创建文件O_TRUNC: 清空文件内容O_APPEND: 追加模式
mode: 文件权限(创建文件时需要)
返回值:
成功: 返回文件描述符(非负整数)
失败: 返回-1
2. 读取文件 -read()
#include <unistd.h> ssize_t read(int fd, void *buf, size_t count);
功能: 从文件读取数据
参数:
fd: 文件描述符buf: 接收数据的缓冲区指针count: 最大读取字节数
返回值:
>0: 实际读取的字节数=0: 文件结束<0: 错误
3. 写入文件 -write()
#include <unistd.h> ssize_t write(int fd, const void *buf, size_t count);
功能: 向文件写入数据
参数:
fd: 文件描述符buf: 要写入的数据指针count: 写入数据的长度
返回值:
>0: 实际写入的字节数=0: 无数据写入(某些设备)<0: 错误
4. 关闭文件 -close()
#include <unistd.h> int close(int fd);
功能: 关闭文件描述符
参数:
fd: 文件描述符
返回值:
成功: 返回0
失败: 返回-1
四、目录操作步骤
1. 打开目录 -opendir()
#include <dirent.h> #include <sys/types.h> DIR *opendir(const char *name);
功能: 打开目录,获得目录流指针
参数:
name: 目录名
返回值:
成功: 返回目录流指针
失败: 返回NULL
2. 读取目录 -readdir()
#include <dirent.h> struct dirent *readdir(DIR *dirp);
功能: 读取目录中的文件信息
参数:
dirp: 目录流指针
返回值:
成功: 返回文件信息结构体指针
失败或结束: 返回NULL
dirent结构体:
struct dirent { ino_t d_ino; // 索引节点号 off_t d_off; // 目录文件中的偏移 unsigned short d_reclen; // 记录长度 unsigned char d_type; // 文件类型 char d_name[256]; // 文件名 };文件类型常量:
DT_DIR: 目录文件DT_REG: 普通文件DT_LNK: 链接文件DT_CHR: 字符设备DT_BLK: 块设备DT_FIFO: 管道DT_SOCK: 套接字
3. 关闭目录 -closedir()
#include <dirent.h> int closedir(DIR *dirp);
功能: 关闭目录流
参数:
dirp: 目录流指针
返回值:
成功: 返回0
失败: 返回-1
五、重要概念总结
1. 文件描述符
非负整数,表示打开的文件
0: 标准输入(stdin)
1: 标准输出(stdout)
2: 标准错误(stderr)
其他: 用户打开的文件
2. 缓冲机制
标准I/O: 带缓冲区,减少系统调用次数
文件I/O: 无缓冲区,直接读写
3. 错误处理
所有系统调用失败返回-1
使用
perror()打印错误信息使用
errno获取错误码
4. 文件权限
创建文件时需要指定权限,常用权限:
0644: 用户读写,组和其他只读0755: 用户读写执行,组和其他读执行
六、使用建议
普通文件操作: 优先使用标准I/O(更高效)
设备文件操作: 使用文件I/O(更直接)
错误检查: 每次调用后都要检查返回值
资源释放: 使用完后及时关闭文件/目录描述符
路径处理: 使用相对路径或绝对路径,注意权限