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

如何用CSVHelper 28.0.1读写动态列CSV至嵌套字典?

用CSVHelper 28.0.1实现动态列CSV的读写(映射为嵌套字典)

针对第一列为Key、其余列数量动态变化的CSV,要实现读写并映射为Dictionary<string, Dictionary<string, string>>类型的查找表,无需定义固定实体类,直接用CSVHelper的基础API即可完成,以下是具体实现:

一、读取CSV到嵌套字典

核心逻辑:先读取所有表头,逐行解析时将第一列值作为外层字典的Key,其余列的表头与对应值组成内层字典。

using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using CsvHelper;
using CsvHelper.Configuration;

public static Dictionary<string, Dictionary<string, string>> ReadCsvToLookupTable(string filePath)
{
    var config = new CsvConfiguration(CultureInfo.InvariantCulture)
    {
        TrimOptions = TrimOptions.Trim,
        AllowComments = false
        // 可根据实际CSV格式添加配置,如分隔符、引号规则等
    };

    var lookupTable = new Dictionary<string, Dictionary<string, string>>();

    using (var reader = new StreamReader(filePath))
    using (var csv = new CsvReader(reader, config))
    {
        csv.Read();
        csv.ReadHeader();
        var headers = csv.HeaderRecord;

        // 提取除Key列外的所有表头
        var valueHeaders = headers.Skip(1).ToList();

        while (csv.Read())
        {
            var key = csv.GetField<string>(headers[0]);
            var innerDict = new Dictionary<string, string>();

            foreach (var header in valueHeaders)
            {
                innerDict[header] = csv.GetField<string>(header);
            }

            lookupTable[key] = innerDict;
        }
    }

    return lookupTable;
}

二、将修改后的嵌套字典写回CSV

核心逻辑:先收集所有需写入的表头(含Key列和所有内层字典中出现的表头),再按表头顺序逐行写入数据,确保所有列都被覆盖。

public static void WriteLookupTableToCsv(string filePath, Dictionary<string, Dictionary<string, string>> lookupTable)
{
    if (lookupTable == null || !lookupTable.Any())
        return;

    var config = new CsvConfiguration(CultureInfo.InvariantCulture)
    {
        TrimOptions = TrimOptions.Trim,
        ShouldQuote = (field, context) => true // 强制给字段加引号,避免特殊字符干扰
    };

    // 收集所有唯一表头:先添加Key列,再合并内层字典的键并去重
    var allHeaders = new List<string> { "Key" }; // 若CSV的Key列名不是"Key",需对应修改
    foreach (var innerDict in lookupTable.Values)
    {
        allHeaders.AddRange(innerDict.Keys.Except(allHeaders));
    }

    using (var writer = new StreamWriter(filePath))
    using (var csv = new CsvWriter(writer, config))
    {
        // 写入表头
        foreach (var header in allHeaders)
        {
            csv.WriteField(header);
        }
        csv.NextRecord();

        // 逐行写入数据
        foreach (var kvp in lookupTable)
        {
            csv.WriteField(kvp.Key);

            // 按表头顺序匹配值,无对应值则写空字符串
            foreach (var header in allHeaders.Skip(1))
            {
                kvp.Value.TryGetValue(header, out var value);
                csv.WriteField(value ?? string.Empty);
            }

            csv.NextRecord();
        }
    }
}

三、使用示例

// 读取CSV文件
var lookupTable = ReadCsvToLookupTable("source.csv");

// 修改数据示例
lookupTable["Key1"]["Header2"] = "UpdatedValue";
lookupTable["Key4"] = new Dictionary<string, string> { { "Header5", "NewData" } };

// 写回修改后的CSV
WriteLookupTableToCsv("updated_source.csv", lookupTable);

注意事项

  • 若CSV的Key列名不是"Key",需同步修改读取时的headers[0]引用,以及写入时allHeaders的初始值。
  • 可根据实际CSV格式调整CsvConfiguration参数,比如自定义分隔符、处理空行规则等。
  • 处理大体积CSV时,上述流式读写的方式已优化内存占用,无需额外调整。

内容的提问来源于stack exchange,提问作者sdrest

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 22:10:31