大数跨境
0
0

用 yield 高效读取超大 CSV,C# 轻松处理 10GB 数据

用 yield 高效读取超大 CSV,C# 轻松处理 10GB 数据 DotNet技术匠
2025-12-02
0
导读:用 C# yield 封装一个CSV文件解析类,5分钟轻松处理10GB的海量数据,内存不爆,速度飞起!

前言

在你的编程旅程中,有没有遇到过这样的“噩梦”场景?

“老板让我处理一个 8GB 的用户数据 CSV 文件,我一加载,电脑直接卡死!”

“这个报表要读取上百万条记录,还没处理完就 OutOfMemory 了……”

……

很熟悉的场景,是不是?

这些问题的本质是:传统方式试图把整个文件“一口吞下”,而我们的内存根本不够用。

你可能不知道,C# 为我们提供了一个优雅的解决方案——yield return。

它就像一个“懒加载”的魔法,让你可以按需生成数据,而不是一次性全部创建。

用它来处理 CSV 文件,你可以做到:

1、无论文件多大,内存只保存当前正在处理的一行,内存占用极低。
2、无需等待整个文件加载完成,解析完第一行就能立刻开始处理,启动速度快
3、轻松与 LINQ 结合,实现 Take()、Where()、Select() 等操作,可组合性强

今天,我们就来手把手教你用 yield 封装一个轻量级的 CSV 解析器,让你在 5 分钟内搞定 10GB 的海量数据!

准备好了吗?Let's go!

封装类

下面是封装的 CSV 解析类,核心就是 yield return 的使用,留意代码中的注释

/// <summary>
/// CSV 文件解析器
/// 使用 yield 实现惰性求值,支持流式处理海量数据
/// </summary>
publicclassCsvParser
{
    /// <summary>
    /// 解析 CSV 文件,返回一个可枚举的序列
    /// </summary>
    /// <typeparam name="T">目标对象类型</typeparam>
    /// <param name="filePath">CSV 文件路径</param>
    /// <param name="mapper">将字符串数组映射为 T 类型对象的函数</param>
    /// <returns>可枚举的 T 类型对象序列</returns>
    public IEnumerable<T> ParseCsvFile<T>(string filePath, Func<string[], T> mapper)
    {
        // 使用 StreamReader 逐行读取文件,确保资源正确释放
        usingvar reader = new StreamReader(filePath);
        
        // 读取第一行作为标题(通常 CSV 第一行是列名)
        string header = reader.ReadLine();
        Console.WriteLine($"CSV标题: {header}");
        
        string line;
        // 循环读取每一行,直到文件末尾
        while ((line = reader.ReadLine()) != null)
        {
            // 按逗号分割每一行,得到字段数组
            var fields = line.Split(',');
            
            // 简单清理字段:去除引号和首尾空格
            // 这里可根据实际业务需要进行处理
            for (int i = 0; i < fields.Length; i++)
            {
                fields[i] = fields[i].Trim('\"').Trim();
            }
            
            // 使用传入的映射函数,将字符串数组转换为业务对象
            // yield return 是关键:它不会立即返回所有数据,
            // 而是在 foreach 遍历时“按需”生成下一条数据
            yield return mapper(fields);
        }
        
        // 注意:using 语句确保 reader 在枚举结束或异常时自动关闭
    }
}

使用示例

假设有一个 User 类,用于存储用户信息:

public class User
{
    public int Id { getset; }
    public string Name { getset; }
    public string Email { getset; }
    public DateTime CreateTime { getset; }
}

现在,我们来使用 CsvParser 处理一个巨大的 CSV 文件:

// 创建解析器实例
var parser = new CsvParser();

// 解析 CSV 文件,返回一个 IEnumerable<User>
// 注意:此时文件并未完全读取,只是建立了“读取计划”
var users = parser.ParseCsvFile(@"D:\data\users.csv", fields => new User
{
    Id = int.Parse(fields[0]),
    Name = fields[1],
    Email = fields[2],
    CreateTime = DateTime.Parse(fields[3])
});

// 开始遍历!数据将逐行读取和处理
// 例如:只处理前 10 条数据(避免一次性输出太多)
foreach (var user in users.Take(10))
{
    Console.WriteLine($"用户: {user.Name}, 邮箱: {user.Email}");
}

// 可以根据实际业务需求做更多操作,比如:
// var activeUsers = users.Where(u => u.CreateTime > DateTime.Now.AddYears(-1));
// var totalUsers = users.Count(); // 注意:这会遍历整个文件

总结

我们用一个简单的 yield return,就实现了一个高效、低内存的 CSV 解析器,内存不再是瓶颈,无论文件是 10MB 还是 10GB,内存占用都几乎不变。

如果你有相类似的业务需求,不妨在你的项目试一试,相信不会让你失望的!

最后
如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。也可以加入微信公众号[DotNet技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长!

作者:小码编匠

出处:gitee.com/smallcore/DotNetCore
声明:网络内容,仅供学习,尊重版权,侵权速删,歉意致谢!



END



方便大家交流、资源共享和共同成长
纯技术交流群,需要加入的小伙伴请扫码,并备注加群



推荐阅读






C# 工业巡检系统:集成海康摄像头、轨道机与 OpenCV 的实战方案
C# + SkiaSharp 批量处理上千张图片,分钟级高效完成
一套工具搞定工业通讯全场景?让 PLC、Modbus、TCP 通信一目了然

.NET 8 + WPF 的 Modbus 智能温湿监控系统

.NET 8 微服务框架长什么样?集成 AI 智能体、自动调度与实时通信

基于 JSON 配置的 .NET 桌面应用自动更新方案

基于 .NET 的可视化流程编辑工业视觉框架

WPF 轻量级插件框架:动态菜单、浮动窗口、热加载 DLL,开箱即用

WPF 智能仓储上位机系统,集成数据采集与轻量级 MES 功能

C# + FFmpeg 一键转码,轻松解决海康视频网页播放难题

C# 工业级全局键鼠行为监测与日志记录工具

开源 .NET 工作流引擎 + 可视化设计,轻松搞定 OA/CRM/ERP 开发
WinForm + STM32 打造稳定好用的工业设备远程升级工具
Visual Studio 2026 上手体验,AI 懂你、界面清爽、协作无缝


觉得有收获?不妨分享让更多人受益

关注「DotNet技术匠」,共同提升技术实力


收藏
点赞
分享
在看

【声明】内容源于网络
0
0
DotNet技术匠
「DotNet技术匠」聚焦.NET核心,分享深度干货、实战技巧、最新资讯、优质资源,助你领跑技术赛道,赋能开发者成长。
内容 1715
粉丝 0
DotNet技术匠 「DotNet技术匠」聚焦.NET核心,分享深度干货、实战技巧、最新资讯、优质资源,助你领跑技术赛道,赋能开发者成长。
总阅读32
粉丝0
内容1.7k