【问题标题】:How to handle empty column in parsing with CsvHelper?使用 CsvHelper 解析时如何处理空列?
【发布时间】:2018-01-24 15:44:14
【问题描述】:

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

[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&lt;BaseFileEntity&gt;());

错误:

为“Test”实体解析“xyz.csv”文件时出错: '[{"Error":"无法执行转换。\r\n Text: ''\r\n
MemberType: System.Int32\r\n 类型转换器: 'CsvHelper.TypeConversion.Int32Converter'","Description":"CsvHelper.TypeConversion.TypeConverterException: 无法执行转换。\r\n 文本: ''\r\n MemberType: System.Int32\r\n 类型转换器: 'CsvHelper.TypeConversion.Int32Converter'\r\n at CsvHelper.Configuration.Configuration.c.<.ctor>b__148_4(CsvHelperException 例外)\r\n 在 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, xyz.cs 中的 IEnumerable1 collection)\r\n at Nec.Stanchion.Business.MasterDataFiles.Handling.MasterDataFileParser.Parse(Stream masterData, Type entityType, IEnumerable1& 错误) 文件"}]'。

原因很清楚,空白或空字符串与int 数据类型不兼容,因此必须有某种方法允许空值或空值与int 数据类型列值。

CsvHelper 版本=6.0.0.0

【问题讨论】:

  • 听起来您应该将数据类型更改为可为空的 int (int?)。
  • 我已经尝试过将其设为可空,但无法正常工作
  • @viveknuna 您可能需要尝试在对象上转换为正确的类型来进行清理,我在下面提供了一个解决方案。

标签: c# csvhelper


【解决方案1】:

我在当前项目中使用的是 CsvHelper 6.1.0,刚刚测试了一个与您类似的用例,csv 文件中的 int 字段为空白,没有问题。这是我正在使用的代码,希望对您有所帮助:

        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
    }
}

【讨论】:

  • 是的,你成功了。配置不知道如何处理对象。在他回复更多信息后,文档将更新答案,我会删除因为你很可能有确切的修复。
  • 但在我的情况下它将如何工作?你能解释一下你的代码吗?
  • 空白或空的正确处理在哪里?
  • 无需处理 - 它可以正常工作。 csv 中为空的 int 字段在对象中将为空。
  • 文档在这里:joshclose.github.io/CsvHelper/mapping。如有任何疑问,我很乐意提供帮助。
【解决方案2】:

我也有这个问题,空值/其他有问题的值在双精度或十进制对象中不例外

我发现的最佳解决方案是这样的:

   //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;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-18
    • 1970-01-01
    相关资源
    最近更新 更多