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

使用fscanf读取不定数量整数及处理超10万份CSV文件技术咨询

嘿,我来帮你搞定这两个问题——先解决用fscanf读取不定数量整数的需求,再聊聊处理10万+CSV文件的高效方案!

一、用fscanf读取不定数量的整数(CSV格式)

CSV里的整数是逗号分隔的,还可能有空字段(连续逗号),我们可以通过循环读取+动态数组来实现:

核心思路

  1. 循环调用fscanf直到文件结束(EOF)
  2. 用%d%*[,]格式字符串:%d读取整数,%*[,]读取逗号但不存储(自动跳过分隔符)
  3. 用动态数组(realloc)存储不定数量的整数,避免内存浪费
  4. 处理空字段:如果fscanf返回0,说明遇到非整数(比如连续逗号),可选择跳过或设默认值

代码示例

#include <stdio.h>
#include <stdlib.h>

int main() {
    FILE *fp = fopen("sample.csv", "r");
    if (!fp) {
        perror("Failed to open file");
        return 1;
    }

    int *nums = NULL;
    int count = 0;
    int num;
    int read_status;

    // 循环读取直到文件结束
    while ((read_status = fscanf(fp, "%d%*[,]", &num)) != EOF) {
        if (read_status == 1) { // 成功读取一个整数
            count++;
            // 动态扩容数组(建议按倍数增长,减少realloc调用次数)
            int *temp = realloc(nums, count * sizeof(int));
            if (!temp) {
                perror("Memory realloc failed");
                free(nums);
                fclose(fp);
                return 1;
            }
            nums = temp;
            nums[count - 1] = num;
        } else {
            // 遇到空字段,可选择跳过或设置默认值(比如nums[count++] = 0)
            continue;
        }
    }

    // 输出读取结果
    printf("Total integers read: %d\n", count);
    for (int i = 0; i < count; i++) {
        printf("%d ", nums[i]);
    }
    printf("\n");

    // 清理资源
    free(nums);
    fclose(fp);
    return 0;
}

注意点

  • 即使CSV最后一个字段后没有逗号,%*[,]也会自动忽略,不影响读取
  • 动态数组按倍数扩容(比如每次扩2倍)能减少realloc的开销
  • 必须检查realloc返回值,避免内存分配失败导致崩溃

二、处理100,000+ CSV文件的可行方案

面对这么大的文件量,核心要抓效率、内存控制和容错性,给你几个实用方向:

1. 并行处理,榨干CPU性能

单线程处理10万文件太慢,必须并行:

  • 线程池实现:用C的pthread搭建线程池,把文件列表分成若干块,每个线程负责一块文件的处理
  • 系统工具辅助:Linux下用xargs -P配合处理程序,比如find ./data -name "*.csv" | xargs -P 8 -n 100 ./csv_processor,用8个进程同时处理,每个进程负责100个文件
  • 注意:线程/进程数不要超过CPU核心数的2倍,避免上下文切换开销过大

2. 替换fscanf,用更快的解析方式

fscanf是格式化IO,大量文本处理时效率不如手动解析:

  • 用fgets读取整行,再手动拆分:比如用strtok按逗号分割字符串,用strtol转整数(比atoi更安全,能检测转换错误)
  • 手动解析能减少IO层的额外开销,速度比fscanf提升明显

3. 严格控制内存,避免OOM

绝对不要一次性加载所有文件到内存:

  • 单个文件逐行处理:读取一行、解析一行、处理一行(比如计算统计值),然后丢弃该行数据
  • 用固定大小缓冲区循环利用,减少频繁内存分配/释放
  • 处理完一个文件立刻关闭,释放文件描述符

4. 批量管理文件,减少目录遍历开销

先一次性收集所有CSV路径,再分批次处理:

  • C语言用glob函数批量获取符合规则的文件路径
  • 或用shell的find命令把所有CSV路径导出到文本文件,程序从该文件读取路径列表
  • 避免反复遍历目录,节省大量IO时间

5. 容错与日志,避免流程中断

10万文件里难免有损坏、权限不足的情况:

  • 处理每个文件前先检查是否能正常打开,用strerror获取错误信息
  • 把错误信息记录到日志文件(比如fprintf(log_fp, "Failed to process %s: %s\n", filename, strerror(errno)))
  • 单个文件处理失败时,跳过它继续处理下一个,不要中断整个流程

6. 优化IO操作,减少磁盘瓶颈

磁盘IO是大量文件处理的主要瓶颈:

  • 批量写入结果:把多个文件的结果缓存到内存缓冲区,满了再一次性写入磁盘
  • 尽量使用顺序IO,避免随机读写
  • 条件允许的话,用SSD代替HDD,大幅提升IO速度

内容的提问来源于stack exchange,提问作者Chi-fung LAM

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:37:54