如何仅用C语言低级IO调用(read、write、open)反向读取文件
仅用open、read、write反向读取文件的实现方法
核心思路
反向读取的关键是通过文件指针偏移从文件末尾开始,分段读取内容后输出。我们会用到系统调用open、read、write,以及lseek(不属于f开头的标准库函数,符合要求)来控制文件指针位置——毕竟要反向读,总得能调整指针位置才行。
具体步骤
- 打开文件:用
open函数以只读模式打开目标文件,获取文件描述符。要注意处理打开失败的情况,比如文件不存在或者权限不足。 - 获取文件大小:通过
lseek将文件指针移到文件末尾,返回值就是文件的总字节数。 - 反向分段读取:从文件末尾开始,每次向前移动固定长度的偏移量(比如用1024字节的缓冲区),读取对应位置的内容,再用
write输出到标准输出或目标文件。 - 处理边界:当剩余字节不足缓冲区大小时,读取剩余的字节数,避免读取无效内容。
代码示例
#include <unistd.h> #include <fcntl.h> #include <stdlib.h> int main(int argc, char *argv[]) { if (argc != 2) { write(STDERR_FILENO, "Usage: ./reverse_read <filename>\n", 31); exit(1); } // 打开文件,只读模式 int fd = open(argv[1], O_RDONLY); if (fd == -1) { write(STDERR_FILENO, "Failed to open file\n", 19); exit(1); } // 获取文件大小:将指针移到末尾,返回值就是总字节数 off_t file_size = lseek(fd, 0, SEEK_END); if (file_size == -1) { write(STDERR_FILENO, "Failed to get file size\n", 22); close(fd); exit(1); } char buf[1024]; off_t current_pos = file_size; ssize_t bytes_read; // 从末尾开始反向读取 while (current_pos > 0) { // 计算本次要读取的字节数:如果剩余字节小于缓冲区大小,就读剩余的 size_t read_size = (current_pos > sizeof(buf)) ? sizeof(buf) : current_pos; // 将指针移到要读取的起始位置:current_pos - read_size if (lseek(fd, current_pos - read_size, SEEK_SET) == -1) { write(STDERR_FILENO, "Failed to seek file\n", 19); close(fd); exit(1); } // 读取内容到缓冲区 bytes_read = read(fd, buf, read_size); if (bytes_read == -1) { write(STDERR_FILENO, "Failed to read file\n", 19); close(fd); exit(1); } // 写入到标准输出 write(STDOUT_FILENO, buf, bytes_read); // 更新当前位置 current_pos -= bytes_read; } close(fd); return 0; }
关键细节说明
- 文件描述符:
open返回的整数是系统级的文件标识,和标准库的FILE*指针不是一回事。 - lseek的作用:
lseek(fd, offset, whence)用来移动文件指针,SEEK_END表示从文件末尾开始计算偏移,SEEK_SET表示从文件开头计算。 - 缓冲区大小:示例中用1024字节的缓冲区,你可以根据需求调整,平衡效率和内存占用。
- 错误处理:每个系统调用都要检查返回值,避免出现文件打开失败、读取失败等异常情况。
内容的提问来源于stack exchange,提问作者Patel
相关产品推荐
相关产品推荐

