如何用C语言read()系统调用逐行读取文件并拆分数据
仅用系统调用实现文件内容的姓名与数字拆分读取
问题背景
作业要求只能使用系统调用操作文件,已完成写入逻辑(将姓名和格式化后的数字按行写入文件),但读取时仅能直接输出文件内容,无法像fscanf那样将每行的姓名、数字分别存入独立变量,且禁止使用结构体。
已实现的写入代码
for (i = 0; strcmp(names[i], "") != 0; i++) { // 将balance转换为格式化字符串存入nums数组 snprintf(nums[i], 100, "%6.2lf", balances[i]); // 写入姓名 write(fd, &names[i], strlen(names[i])); write(fd, " ", strlen(" ")); // 写入数字字符串 write(fd, &nums[i], strlen(nums[i])); write(fd, "\n", strlen("\n")); }
解决方案:手动解析缓冲区内容
系统调用read只能按字节读取数据,无法直接解析格式,需要手动实现字符串拆分逻辑,步骤如下:
- 维护一个全局缓冲区,暂存
read读取的字节,处理跨块的不完整行 - 在缓冲区中定位空格(姓名与数字的分隔符)和换行(行结束符),逐行拆分
- 提取空格前的内容存入姓名变量,将空格后的字符串转为
double类型存入数字变量 - 解析完一行后,将缓冲区剩余的未处理数据移到起始位置,继续读取新数据
完整读取示例代码
#include <unistd.h> #include <fcntl.h> #include <string.h> #include <stdlib.h> #include <stdio.h> #define BUF_SIZE 1024 int main() { int fd = open("gifts2.dat", O_RDONLY); if (fd == -1) { perror("open failed"); return 1; } char buf[BUF_SIZE]; char leftover[BUF_SIZE] = {0}; // 存储未处理的剩余数据 ssize_t bytes_read; char *space_ptr, *newline_ptr; char name[100]; double balance; while ((bytes_read = read(fd, buf, BUF_SIZE - strlen(leftover) - 1)) > 0) { // 将剩余数据与新读取的数据拼接 strcat(leftover, buf); buf[bytes_read] = '\0'; // 确保字符串终止 // 循环解析每一行 while ((newline_ptr = strchr(leftover, '\n')) != NULL) { *newline_ptr = '\0'; // 将换行符替换为终止符,分割出当前行 // 查找姓名与数字的分隔空格 space_ptr = strchr(leftover, ' '); if (space_ptr == NULL) { // 格式错误,跳过该行 memmove(leftover, newline_ptr + 1, strlen(newline_ptr + 1) + 1); continue; } *space_ptr = '\0'; // 分割姓名部分 // 复制姓名到变量 strncpy(name, leftover, sizeof(name) - 1); name[sizeof(name)-1] = '\0'; // 确保字符串终止 // 将数字字符串转换为double balance = atof(space_ptr + 1); // 这里替换为你的业务逻辑 printf("姓名:%s,余额:%.2lf\n", name, balance); // 将剩余未处理的数据移到缓冲区起始位置 memmove(leftover, newline_ptr + 1, strlen(newline_ptr + 1) + 1); } } // 处理文件末尾可能剩余的最后一行(无换行的情况) if (strlen(leftover) > 0) { space_ptr = strchr(leftover, ' '); if (space_ptr != NULL) { *space_ptr = '\0'; strncpy(name, leftover, sizeof(name)-1); name[sizeof(name)-1] = '\0'; balance = atof(space_ptr + 1); printf("姓名:%s,余额:%.2lf\n", name, balance); } } close(fd); return 0; }
关键注意点
- 缓冲区大小:设置合理的
BUF_SIZE,平衡读取效率与内存占用 - 剩余数据处理:必须处理跨
read调用的不完整行,否则会丢失数据 - 格式校验:实际使用时可增加更多格式检查(比如数字部分是否合法),避免非法数据导致程序异常
- 错误处理:所有系统调用(
open、read、close)都要检查返回值,及时处理错误
内容的提问来源于stack exchange,提问作者Dieynaba
相关产品推荐
相关产品推荐

