使用CsvHelper的CsvDataReader时如何为空字符串指定默认int值
如何在使用CsvReader和CsvDataReader加载CSV到DataTable时,为空字符串的int列指定默认值0?
问题描述
我希望使用CsvReader和CsvDataReader将CSV数据加载到预定义列类型的DataTable中,但当CSV字段出现空字符串(比如连续的;;)时,int类型的列(例如Credits列)会解析失败,抛出类似Input string was not in a correct format.Couldn't store <> in Credits Column. Expected type is Int32的异常。请问如何在这种情况下给Credits列指定默认的int值0?
示例代码
// 构建DataTable DataTable dataTable = new DataTable(); dataTable.Columns.Add(new DataColumn("Name", typeof(string))); dataTable.Columns.Add(new DataColumn("Credits", typeof(int))); dataTable.Columns.Add(new DataColumn("Notes", typeof(string))); dataTable.Columns.Add(new DataColumn("LastLogin", typeof(DateTime))); dataTable.Columns.Add(new DataColumn("Balance", typeof(decimal))); // 准备CSV内容 StringBuilder sbInput = new StringBuilder(); sbInput.AppendLine("Name;Credits;Notes;LastLogin;Balance"); sbInput.AppendLine("Michael;2433;Good guy;2023-03-28;736,26"); sbInput.AppendLine("John;;Bad guy;2023-04-01;-49,25"); // 配置CsvReader CsvConfiguration csvConfiguration = new CsvConfiguration(CultureInfo.InvariantCulture) { NewLine = Environment.NewLine, Delimiter = ";", Mode = CsvMode.NoEscape, TrimOptions = TrimOptions.Trim, UseNewObjectForNullReferenceMembers = true }; // 读取CSV流并加载到DataTable using (var csvReader = new CsvReader(new StringReader(sbInput.ToString()), csvConfiguration)) { using (var csvDataReader = new CsvDataReader(csvReader)) { // 当出现John;;Bad guy这样的行时会抛出异常 // 异常信息:Input string was not in a correct format.Couldn't store <> in Credits Column. Expected type is Int32. dataTable.Load(csvDataReader); } }
解决方案
方法一:自定义CsvHelper类型转换器(全局生效)
通过自定义类型转换器,让CsvReader在解析int类型字段时,自动将空字符串转换为0。
- 定义自定义转换器类:
public class Int32WithDefaultConverter : DefaultTypeConverter { public override object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData) { // 处理空或空白字符串,返回默认值0 if (string.IsNullOrWhiteSpace(text)) { return 0; } // 非空时按正常逻辑解析 return int.Parse(text, memberMapData.TypeConverterOptions.CultureInfo); } }
- 在Csv配置中注册该转换器:
CsvConfiguration csvConfiguration = new CsvConfiguration(CultureInfo.InvariantCulture) { NewLine = Environment.NewLine, Delimiter = ";", Mode = CsvMode.NoEscape, TrimOptions = TrimOptions.Trim, UseNewObjectForNullReferenceMembers = true }; // 为int类型注册自定义转换器 csvConfiguration.TypeConverterCache.AddConverter<int>(new Int32WithDefaultConverter());
修改后,CsvReader会自动将空的int字段解析为0,DataTable加载时不会再抛出异常。
方法二:监听DataTable的ColumnChanging事件(针对特定列)
如果只需要对单个列(比如Credits)设置默认值,可以通过DataTable的ColumnChanging事件处理:
// 在创建DataTable后添加事件监听 dataTable.ColumnChanging += (sender, e) => { // 仅针对Credits列,当值为DBNull时设置为0 if (e.Column.ColumnName == "Credits" && e.ProposedValue == DBNull.Value) { e.ProposedValue = 0; } };
这种方式更灵活,可针对特定列单独处理,但需要确保CsvDataReader将空字符串转换为DBNull.Value(默认配置下即可实现)。
内容的提问来源于stack exchange,提问作者Brøgger
相关产品推荐
相关产品推荐

