【问题标题】:Trying to parse CSV rows into multiple classes with CsvHelper尝试使用 CsvHelper 将 CSV 行解析为多个类
【发布时间】:2019-10-05 01:28:15
【问题描述】:

我有一个带有单个标题行的 CSV。每行的某些列需要映射到一个类,而该行的其他列需要映射到不同的类。

我试过了,但没有成功:

using(var reader = new StreamReader(@"c:\temp\myfile.csv"))
{
    using(var csv = new CsvReader(reader))
    {
       csv.Configuration.RegisterClassMap<ClientMap>();
       csv.Configuration.RegisterClassMap<BookingMap>();

       var bookings = csv.GetRecords<Booking>();
       ... //iterate over bookings and write to Console

       reader.BaseStream.Position = 0;

       var clients = csv.GetRecords<Client>();
       ... //iterate over clients and write to Console
    }
}

public class Client {
   public string Firstname {get; set;}
   public string Lastname {get; set;}
   public AgesEnum Age {get; set;}
}

public class Booking {
    public string ExternalId {get; set;}
    public string Status {get; set;}
}

地图

public class ClientMap : ClassMap<Client> 
{
   public ClientMap()
   {
       Map(m => m.Firstname).Name("FIRSTNAM");
       Map(m => m.Lastname).Name("LASTNAME");
       Map(m => m.Age).ConvertUsing(row =>{
          var age = row.GetField<int>("AGE");

          if(age < 2)
             return AgesEnum.Baby;
          if(age < 10)
             return AgesEnum.Young;
          if(age < 40)
             return AgesEnum.Middle;
          return AgesEnum.Old;
       } );
    }
}


public BookingMap : ClassMap<Booking>
{
    public BookingMap()
    {
        Map(b => b.ExternalId).Name("SYSID");
        Map(b => b.Status);
    }
}

当我运行它时会发生什么,bookings 得到很好的返回,我可以迭代它们。但是,我在GetRecords&lt;Client&gt;() 行收到一个错误,指出

无法执行转换。文本:“年龄”成员类型:TypeConverter:“CsvHelper.TypeConversion.Int32Converter”

如果我注释掉与 Bookings 相关的所有代码并只执行GetRecords&lt;Client&gt;(),我不会收到错误。

为什么这不起作用?我必须设置一个全新的StreamReader吗?

【问题讨论】:

  • 您是否有可能在某些时候遗漏了 (int) 演员表?我不确定 CsvHelper 是否可以转换自定义枚举。无论是那个还是您的自定义“AgesEnum”都没有每个可能的字符串的 Int 值。

标签: c# csvhelper


【解决方案1】:

问题是您将流位置设置回开头,CsvReader 认为您在获得预订时已经读取了标题,因此它再次将第一行作为数据而不是标题读取。您需要再次手动读取标题。

using(var reader = new StreamReader(@"c:\temp\myfile.csv"))
{
    using(var csv = new CsvReader(reader))
    {
       csv.Configuration.RegisterClassMap<ClientMap>();
       csv.Configuration.RegisterClassMap<BookingMap>();

       var bookings = csv.GetRecords<Booking>();
       ... //iterate over bookings and write to Console

       reader.BaseStream.Position = 0;

       csv.Read();
       csv.ReadHeader();

       var clients = csv.GetRecords<Client>();
       ... //iterate over clients and write to Console
    }
}

【讨论】:

    【解决方案2】:

    我想你可能会发现一些关于使用 Enums 和 CsvHelper right here

    的有趣之处

    【讨论】:

    • 我不认为这是苹果对苹果。我没有尝试将从 CSV 读取的值转换为匹配的 Enum 值。确实没有进行转换或转换——我只是根据 CSV 中的其他值设置一个枚举值。另外,只要我不先进行预订转换,代码就可以工作。
    • 你能在 Debug 中看到 StreamReader 中的数据吗?进行预订转换后是否发生了变化?将位置设置为 0 时,对象会发生什么情况?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-12
    • 1970-01-01
    • 2017-04-30
    • 1970-01-01
    • 2013-04-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多