如何仅使用read(2)和write(2)系统调用改写实现类head命令的C代码
基于read/write系统调用实现类head命令的代码调整方案
直接替换为read/write后输出整个文件的核心原因:
fgets是标准库封装的按行读取接口,会自动识别换行符做行截断,但read系统调用仅按字节读取内容,没有行逻辑,你需要自行实现换行符统计,达到指定行数后终止读取输出即可。
完整实现代码
#include <unistd.h> #include <fcntl.h> #include <stdlib.h> #define BUFFSIZE 10000 int main (int argc, char* argv[]) { // 简单参数校验,用法示例:./myhead -n 5 test.txt if (argc != 4) { char usage[] = "Usage: ./myhead -n <输出行数> <目标文件路径>\n"; write(STDERR_FILENO, usage, sizeof(usage)-1); exit(1); } int line_limit = atoi(argv[2]); if (line_limit <= 0) { char err[] = "输出行数必须为正整数\n"; write(STDERR_FILENO, err, sizeof(err)-1); exit(1); } int fd = open(argv[3], O_RDONLY); if (fd < 0) { char err[] = "文件打开失败\n"; write(STDERR_FILENO, err, sizeof(err)-1); exit(1); } char buffer[BUFFSIZE]; ssize_t read_bytes; int line_count = 0; int output_pos = 0; while ((read_bytes = read(fd, buffer, BUFFSIZE)) > 0) { // 逐字节遍历当前缓冲区内容,统计换行 for (int i = 0; i < read_bytes; i++) { if (buffer[i] == '\n') { line_count++; // 达到行数上限,输出到当前换行符位置后终止 if (line_count == line_limit) { write(STDOUT_FILENO, buffer + output_pos, i - output_pos + 1); goto end_process; } } } // 缓冲区未触发行数上限,全部输出 write(STDOUT_FILENO, buffer + output_pos, read_bytes - output_pos); } end_process: close(fd); return 0; }
核心逻辑说明
- 用
open()系统调用替代fopen(),返回的整数文件描述符替代标准库的FILE*指针,打开模式指定O_RDONLY只读即可 - 每次调用
read()读取最多BUFFSIZE字节的内容到缓冲区,逐字节遍历检查换行符\n - 每识别到一个换行符就累加行计数,达到指定行数时输出当前位置到换行符的内容后直接终止流程
- 输出全部使用
write()写入到STDOUT_FILENO(标准输出的固定文件描述符为1),完全不依赖标准IO库函数 - 流程结束前调用
close()关闭文件描述符,避免资源泄漏
内容的提问来源于stack exchange,提问作者Belle247
相关产品推荐
相关产品推荐

