You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 18:38:03