如何在使用CsvHelper解析时处理空列?

6

我有一个CSV文件,我正在尝试解析它,但在整数数据类型列上出现以下错误。在文件中,我为此列传递了空值或空白值。

[AutoMap(typeof(Test))]
[FileEntity("Test")]
public class TestFileEntity : BaseFileEntity
{
    [CsvFileColumn(1)]
    public int TestId { get; set; }
}

public IEnumerable<BaseFileEntity> Parse(Stream masterData, Type entityType, out IEnumerable<MasterDataFileParserError> errors)
{
    var list = new List<BaseFileEntity>();
    var errorList = new List<MasterDataFileParserError>();

    try
    {
        using (var reader = new StreamReader(masterData))
        {
            var parser = new CsvReader(reader, new CsvHelper.Configuration.Configuration
            {
                HasHeaderRecord = true,
                HeaderValidated = null,
                MissingFieldFound = null
            });

            list.AddRange(parser.GetRecords(entityType).Cast<BaseFileEntity>());
        }
    }
    catch (Exception ex)
    {
        if (ex.Data == null || ex.Data.Count == 0)
        {
            errorList.Add(new MasterDataFileParserError
            {
                Error = ex.Message,
                Description = ex.ToString()
            });
        }
        else
        {
            foreach (var key in ex.Data.Keys)
            {
                errorList.Add(new MasterDataFileParserError
                {
                    Error = ex.Message,
                    Description = $"{key}: {ex.Data[key]}"
                });
            }
        }
    }

    errors = errorList;

    return list;
}

在这一行出现了异常:list.AddRange(parser.GetRecords(entityType).Cast<BaseFileEntity>());

错误信息:

解析“xyz.csv”文件中的“Test”实体时发生错误: '[{"Error":"The conversion cannot be performed.\r\n Text: ''\r\n
MemberType: System.Int32\r\n TypeConverter: 'CsvHelper.TypeConversion.Int32Converter'","Description":"CsvHelper.TypeConversion.TypeConverterException: The conversion cannot be performed.\r\n Text: ''\r\n MemberType: System.Int32\r\n TypeConverter: 'CsvHelper.TypeConversion.Int32Converter'\r\n at CsvHelper.Configuration.Configuration.<>c.<.ctor>b__148_4(CsvHelperException exception)\r\n at CsvHelper.CsvReader.d__65.MoveNext()\r\n at System.Linq.Enumerable.d__341.MoveNext()\r\n at System.Collections.Generic.List1.AddEnumerable(IEnumerable1 enumerable)\r\n at System.Collections.Generic.List1.InsertRange(Int32 index, IEnumerable1 collection)\r\n at Nec.Stanchion.Business.MasterDataFiles.Handling.MasterDataFileParser.Parse(Stream masterData, Type entityType, IEnumerable1& errors) in xyz.cs 文件"}]'。

原因很明显,空字符串不能与int数据类型兼容,所以必须有一种方法来允许int数据类型列值为空或null。

CsvHelper版本=6.0.0.0


听起来你应该将数据类型更改为可空整数(int?)。 - bornfromanegg
我已经尝试过将其设为可空,但没有起作用。 - Vivek Nuna
@viveknuna,您可能需要通过尝试将对象转换为正确的类型来进行清理,我在下面提供了一个解决方案。 - Greg
3个回答

7
我正在使用CsvHelper 6.1.0来开展我的项目,刚测试了一个和你类似的用例,在CSV文件中整数字段为空,并没有出现问题。这是我使用的代码,希望能对你有所帮助:
        CsvReader csv = new CsvReader(new StreamReader(file.OpenReadStream()));
        csv.Configuration.RegisterClassMap<PessoaCSVMap>();
        csv.Configuration.Delimiter = ";";
        csv.Configuration.HeaderValidated = null;
        csv.Configuration.MissingFieldFound = null;
        List<Pessoas> pessoas = csv.GetRecords<Pessoas>().ToList();

public sealed class PessoaCSVMap : ClassMap<Pessoas>
{
    public PessoaCSVMap()
    {
        Map(m => m.Nome).Name("Nome", "Name");
        ... etc
    }
}

是的,你做得很好。配置不知道如何处理对象。在他回复更多信息并准备更新答案文档后,我会删除它,因为你很可能已经找到了确切的解决方法。 - Greg
1
但是它在我的情况下如何工作呢?你能否稍微解释一下你的代码? - Vivek Nuna
空白或空的处理在哪里? - Vivek Nuna
没有任何处理 - 它只是工作。在 CSV 中为空的 Int 字段将在对象中为 null。 - Matheus Lacerda
文档在这里:http://joshclose.github.io/CsvHelper/mapping。如果还有疑问,我很乐意帮助。 - Matheus Lacerda
PessoaCSMap类有什么重要性? - Vivek Nuna

5

我也遇到了这个问题,即空值或其他问题值不能被双精度或十进制对象接受。

我找到的最佳解决方案如下:

   //first inject the class map
   CsvReader csv = new CsvReader(new 
   StreamReader(file.OpenReadStream()));
   csv.Configuration.RegisterClassMap<SomeEntityClassMap>();
   var records = csv.GetRecords<SomeEntity>().ToList();
 
public class SomeEntityClassMap : ClassMap<SomeEntity>
{
    public SomeEntityClassMap()
    {
        //use the converter on double or decimal types
        Map(x => x.Price).TypeConverter<DoubleConverter>();
        Map(x => x.Cost).TypeConverter<DoubleConverter>();
    }
}

public class DoubleConverter : DefaultTypeConverter
{
    public override object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData)
    {
        if(double.TryParse(text, out var result))
            return result;

        return 0;
    }
}

-1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接