如何在CsvHelper解析CSV时处理int类型列的空值?
解决CsvHelper 6.0.0解析空字符串到int列的转换错误问题
我来帮你搞定这个空字符串转int报错的问题,结合你使用的CsvHelper 6.0.0版本,这里有几个实用的解决方案,你可以根据业务需求选择:
方案1:把int改成可空int(int?)
这是最省事的办法——因为空值本来就没法映射到非空的int类型,把属性改成可空int后,CsvHelper会自动把空字符串解析成null,完全不用额外配置:
修改你的实体类代码:
[AutoMap(typeof(Test))] [FileEntity("Test")] public class TestFileEntity : BaseFileEntity { [CsvFileColumn(1)] public int? TestId { get; set; } // 将int改为int? }
这样处理后,空值就会被正确解析,不会再抛出转换异常。
方案2:自定义Int32类型转换器
要是业务上要求这个字段必须是非空int,那可以自定义一个类型转换器,专门处理空字符串的情况(比如返回0或者你需要的默认值):
首先写一个自定义转换器:
public class NullableIntConverter : Int32Converter { public override object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData) { // 如果文本是空或空白,返回默认值0,你也可以改成其他符合业务的值 if (string.IsNullOrWhiteSpace(text)) { return 0; } // 非空的话就用默认的转换逻辑 return base.ConvertFromString(text, row, memberMapData); } }
接下来有两种方式应用这个转换器:
方式A:全局注册(所有int类型都生效)
修改你的Parse方法里的CsvHelper配置:
var parser = new CsvReader(reader, new CsvHelper.Configuration.Configuration { HasHeaderRecord = true, HeaderValidated = null, MissingFieldFound = null }); // 把自定义转换器注册到int类型 parser.Configuration.TypeConverterCache.AddConverter<int>(new NullableIntConverter());
方式B:单独给属性标记(只对这个字段生效)
修改实体类的属性:
[AutoMap(typeof(Test))] [FileEntity("Test")] public class TestFileEntity : BaseFileEntity { [CsvFileColumn(1)] [TypeConverter(typeof(NullableIntConverter))] // 给这个属性应用自定义转换器 public int TestId { get; set; } }
方案3:配置转换错误回调,记录错误不中断解析
如果你想保留非空int类型,同时希望遇到空值时记录错误但继续解析其他行,可以配置CsvHelper的错误处理回调:
修改Parse方法中的配置部分:
var config = new CsvHelper.Configuration.Configuration { HasHeaderRecord = true, HeaderValidated = null, MissingFieldFound = null }; // 先把空字符串添加为int类型的空值标识 config.TypeConverterOptionsCache.GetOptions<int>().NullValues.Add(""); // 设置转换错误的回调逻辑 config.CsvExceptionCallback = (exception, context) => { // 把错误信息添加到你的错误列表里 errorList.Add(new MasterDataFileParserError { Error = exception.Message, Description = $"行号 {context.Row}: {exception.ToString()}" }); // 返回true表示跳过当前错误行,继续解析后续内容 return true; }; using (var reader = new StreamReader(masterData)) { var parser = new CsvReader(reader, config); list.AddRange(parser.GetRecords(entityType).Cast<BaseFileEntity>()); }
注意在6.0.0版本中,CsvExceptionCallback返回true就会跳过错误行,继续处理剩下的数据。
选哪个方案?
- 如果业务允许该字段为空,优先选方案1,最符合语义,代码改动最少。
- 如果必须是非空int,且要统一把空值转成默认值,选方案2。
- 如果需要记录错误但不中断整个解析流程,选方案3。
内容的提问来源于stack exchange,提问作者Vivek Nuna
相关产品推荐
相关产品推荐

