使用fscanf读取不定数量整数及处理超10万份CSV文件技术咨询
嘿,我来帮你搞定这两个问题——先解决用fscanf读取不定数量整数的需求,再聊聊处理10万+CSV文件的高效方案!
一、用fscanf读取不定数量的整数(CSV格式)
CSV里的整数是逗号分隔的,还可能有空字段(连续逗号),我们可以通过循环读取+动态数组来实现:
核心思路
- 循环调用
fscanf直到文件结束(EOF) - 用
%d%*[,]格式字符串:%d读取整数,%*[,]读取逗号但不存储(自动跳过分隔符) - 用动态数组(
realloc)存储不定数量的整数,避免内存浪费 - 处理空字段:如果
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
相关产品推荐
相关产品推荐

