使用CsvHelper修改CSV时如何自动匹配原字段引号格式?
解决方案:自动匹配原CSV的引号/格式输出
核心思路
CsvHelper可以在读取原文件时自动解析每列的类型和引号行为,我们只需要复用读取阶段获取的列配置到写入环节,就能避免硬编码列名和类型,保持原文件的引号格式。
具体实现代码
1. 读取原文件并记录列类型
先读取CSV文件,同时获取每列的原始类型信息,用DynamicRecord保存所有行数据:
using CsvHelper; using CsvHelper.Configuration; using System.Globalization; using System.IO; using System.Linq; var config = new CsvConfiguration(CultureInfo.InvariantCulture) { // 匹配原文件的基础配置,根据实际情况调整分隔符、引号字符等 Delimiter = ",", Quote = '"', Mode = CsvMode.RFC4180, }; List<dynamic> records; List<Type> columnTypes; using (var reader = new StreamReader("input.csv")) using (var csvReader = new CsvReader(reader, config)) { csvReader.Read(); csvReader.ReadHeader(); // 获取每列的原始类型 columnTypes = csvReader.Context.HeaderRecord .Select(header => csvReader.GetFieldType(header)) .ToList(); // 读取所有记录 records = csvReader.GetRecords<dynamic>().ToList(); } // 修改指定列的值(示例:替换ColumnA、ColumnB、ColumnC的内容) foreach (var record in records) { record.ColumnA = "Updated Text Value"; record.ColumnB = 9876; record.ColumnC = 123456789L; }
2. 动态创建映射规则匹配原格式
基于读取到的列类型,动态生成ClassMap,让CsvHelper写入时自动沿用原格式:
using CsvHelper.TypeConversion; // 创建动态映射 var dynamicMap = new DefaultClassMap<dynamic>(); for (int i = 0; i < columnTypes.Count; i++) { var header = records[0].GetType().GetProperties()[i].Name; var columnType = columnTypes[i]; // 为每列绑定对应类型的转换器,自动处理引号逻辑 dynamicMap.Map(typeof(dynamic), header) .TypeConverter(TypeConverterFactory.GetConverter(columnType)) .Index(i); } // 写入修改后的文件 using (var writer = new StreamWriter("output.csv")) using (var csvWriter = new CsvWriter(writer, config)) { csvWriter.Context.RegisterClassMap(dynamicMap); csvWriter.WriteHeader<dynamic>(); csvWriter.NextRecord(); csvWriter.WriteRecords(records); }
注意事项
- 如果原文件存在类型混杂的列(比如同一列既有文本又有数值),可以手动指定该列的类型转换器(比如用
StringConverter)来保留原始格式。 - 确保
CsvConfiguration的参数(分隔符、引号等)和原文件完全一致,否则读取的列类型可能出现偏差。 - v33.0.1版本中
DynamicRecord的属性直接对应列名,修改值时要保证列名拼写和原文件完全匹配。
内容的提问来源于stack exchange,提问作者Kish Baley
相关产品推荐
相关产品推荐

