
后端数据工程【免费下载链接】CsvHelperLibrary to help reading and writing CSV files项目地址https://gitcode.com/gh_mirrors/cs/CsvHelper点击查看免费下载导读现实世界中的 CSV 数据并非总是拥有唯一表头当同一列名在首行出现多次例如Name,Name表示 first name 与 last name 两列时CsvHelper 默认无法区分它们。本指南围绕仓库文档 mapping-duplicate-names/index.md 讲解如何通过名称索引Name Index解决这一场景你将掌握NameIndex()映射 API、[NameIndex]特性以及背后的GetFieldIndex索引解析原理并能正确处理读、写两侧的同名列映射。什么是名称索引Name Index核心概念只有一句话名称索引指的是同名表头出现的第几次第 0 次、第 1 次……而不是该列在整个 CSV 中的物理位置。例如下列数据Id,Name,Name 1,first,last两列Name的物理位置分别是索引 1 和索引 2但它们的名称索引分别是0和1——因为第一个Name是第 0 次出现第二个Name是第 1 次出现。这是 CsvHelper 判断同名表头时使用的计数口径与列号无关。使用 ClassMap 映射同名表头官方示例通过ClassMapT完成映射。为了让它能直接运行这里补全了缺失的using并修正了原文档示例中的笔误{ get set; }缺少分号、混用 Tab/空格缩进using System.Globalization; using System.IO; using CsvHelper; using CsvHelper.Configuration; void Main() { using (var reader new StreamReader(path\\to\\file.csv)) using (var csv new CsvReader(reader, CultureInfo.InvariantCulture)) { csv.Context.RegisterClassMapFooMap(); var records csv.GetRecordsFoo(); } } public class Foo { public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } } public sealed class FooMap : ClassMapFoo { public FooMap() { Map(m m.Id); Map(m m.FirstName).Name(Name).NameIndex(0); Map(m m.LastName).Name(Name).NameIndex(1); } }要点拆解Map(m m.FirstName).Name(Name)与Map(m m.LastName).Name(Name)都声明列名是Name.NameIndex(0)把FirstName绑定到第一次出现的Name列即数据行中的first.NameIndex(1)把LastName绑定到第二次出现的Name列即数据行中的last。注意Name和NameIndex必须成对使用才有效NameIndex的意义是在名为X的表头中取第N个单独使用NameIndex而没有设置名称时没有任何定位作用。用 [NameIndex] 特性直接标注属性如果不写 ClassMap也可以直接在属性上使用CsvHelper.Configuration.Attributes.NameIndex特性。仓库测试 NameIndexTests.cs 提供了等价写法using System.Globalization; using System.IO; using System.Linq; using CsvHelper; using CsvHelper.Configuration.Attributes; private class NameIndexClass { public int Id { get; set; } [NameIndex(1)] public string? Name { get; set; } } using (var reader new StringReader(Id,Name,Name\r\n1,one,two\r\n)) using (var csv new CsvReader(reader, CultureInfo.InvariantCulture)) { var records csv.GetRecordsNameIndexClass().ToList(); // records[0].Id 1 // records[0].Name two绑定到第二个 Name 列 }从特性源码 NameIndexAttribute.cs 可以看到该特性声明为AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter同时实现了IMemberMapper与IParameterMapper并通过ApplyTo把值写入memberMap.Data.NameIndex/parameterMap.Data.NameIndex。这意味着它不仅能用于属性和字段也能用于构造函数参数的映射仓库中存在对应的NameIndexAttributeTests.cs与NameIndexMapTests.cs测试用例例如通过参数映射把一个同名表头列注入构造函数参数。写入场景同名列头也能按 NameIndex 输出NameIndex同样作用于写入过程。在 CsvWriterMappingTests.cs 中可以看到一个多个属性映射到同一个列名的写入用例private sealed class SameNameMultipleTimesClassMap : ClassMapSameNameMultipleTimesClass { public SameNameMultipleTimesClassMap() { Map(m m.Name1).Name(ColumnName).NameIndex(1); Map(m m.Name2).Name(ColumnName).NameIndex(2); Map(m m.Name3).Name(ColumnName).NameIndex(0); } }注意这里 NameIndex 的取值1、2、0是乱序的这恰好印证了名称索引是第几次出现而非写入顺序写入时 CsvHelper 会按 NameIndex 的排序输出列最终表头仍是ColumnName,ColumnName,ColumnName三列且列顺序按名称索引排序。源码原理GetFieldIndex 如何定位同名表头阅读阶段最终都由 CsvReader.cs 的GetFieldIndex方法完成解析其核心逻辑如下前置校验如果没有 header record或尚未调用ReadHeader()直接抛出ReaderException遍历候选名称对names参数即Name()指定的一个或多个名称逐个经PrepareHeaderForMatch处理在namedIndexes字典中查找第一个命中的名称校验名称索引存在性if (name null || index namedIndexes[name].Count)说明第index次出现的同名表头不存在——这是字段缺失当非isTryGet且非 optional 时会触发MissingFieldFound委托回调见 CsvReader.cs随后返回-1结果缓存命中后将nameKey string.Join(_, names) index写入namedIndexCache避免重复遍历。注释明确指出该缓存对使用ConvertUsing的映射有显著加速返回物理列索引return namedIndexes[name][index]——取的是该名称第index次出现对应的真实列位置。namedIndexes本质上是一个名称 → 该名称所有出现位置的列表的索引表因此同名表头无论出现几次都能通过index精确命中某一列。这正是名称索引计数法与物理列号两种口径的最终交汇点映射时给的是名称索引解析时换算回列位置。边界情况与注意事项索引越界即字段缺失如果 CSV 中Name只出现 1 次而你映射了NameIndex(1)GetFieldIndex会判定字段缺失并触发MissingFieldFound默认抛出MissingFieldException。可通过配置MissingFieldFound委托自定义处理逻辑参考 Delegates/MissingFieldFound.cs。索引从 0 开始第一个同名表头的 NameIndex 是0这与多数程序语言数组下标习惯一致但和第 1 列的人类直觉不同容易踩坑。默认索引为 0GetFieldIndex(string name, int index 0, ...)中 index 默认为0所以单表头场景下不写NameIndex也能取到第一个匹配列只有出现重复名称时才必须显式区分。无表头记录时不可用名称索引依赖表头行定位若配置了HasHeaderRecord false无表头应改用Index()按物理列号映射参见同目录下的 mapping-by-index 示例。与替代名称Name(a, b)的关系Name支持传入多个候选名解析时按声明顺序取第一个命中的名称NameIndex作用于最终命中的那个名称两者可以组合使用以实现多个别名 同名多次出现的复杂表头。小结处理重复表头是 CSV 数据清洗中的高频场景。CsvHelper 通过名称索引这一计数口径把第 N 次出现的某列从同名表头中精确分离出来读侧由GetFieldIndex在namedIndexes索引表中完成换算写侧按名称索引排序输出既可以用ClassMap的.Name().NameIndex()链式调用也可以用[NameIndex]特性直标属性还可用于构造函数参数映射。把握NameIndex 是第几次出现、而非列位置这一核心语义即可在各种同名表头的数据上写出清晰、可维护的映射配置。赞分享后端数据工程【免费下载链接】CsvHelperLibrary to help reading and writing CSV files项目地址https://gitcode.com/gh_mirrors/cs/CsvHelper点击查看免费下载相关推荐KLayout中数字开头的图层名称映射问题解析KLayout中数字开头的图层名称映射问题解析 在使用KLayout进行版图设计时图层名称通常以字母开头但在某些特殊情况下如使用特定工艺设计套件PDK时硬件开发桌面应用图形学0168. Excel 表列名称解析LeetCode 经典进制转换与字符映射题解0168. Excel 表列名称解析LeetCode 经典进制转换与字符映射题解 本篇指南基于「算法通关手册」AlgoNote仓库中的 0168. Exc教程文档知识库上一篇SLIP线性探针Linear Probe实战迁移学习性能优化的10个技巧下一篇wiliwili B站客户端在 Switch 大气层上怎么装桌面图标、黑屏、连不上网一次说清创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考