文件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(更直接)
-
错误检查: 每次调用后都要检查返回值
-
资源释放: 使用完后及时关闭文件/目录描述符
-
路径处理: 使用相对路径或绝对路径,注意权限