【问题标题】:CsvHelper - validate whole rowCsvHelper - 验证整行
【发布时间】:2019-09-05 12:02:53
【问题描述】:

问题

我最近开始了解有关 csvHelper 的更多信息,我需要有关如何实现目标的建议。

我有一个包含一些用户记录(数千到数十万条记录)的 CSV 文件,我需要解析文件并验证/处理数据。我需要做的是两件事:

  1. 我需要一种方法来在读取整行时对其进行验证

    • 记录包含日期范围,我需要验证它是有效范围
    • 如果不是,我需要将违规行写入错误文件
  2. 一条记录也可以在不同的日期范围内多次出现,我需要验证这些范围不重叠,如果重叠,请将整个原始行写入错误文件 p>

我基本上可以用一种方法来保留整个原始行以及解析的数据,但是在原始数据仍然可用时验证整行的方法会更好。


问题

是否有一些事件/操作隐藏在某处,我可以在数据行创建之后但将其添加到集合之前对其进行验证?

如果没有,有没有办法将整个 RAW 行保存到记录中,以便我可以在解析后验证该行,如果它无效,对它们进行我需要的处理?


我拥有的代码

我创建的是这样的记录类:

class Record
{  //simplified and omitted fluff for brevity
   string Login
   string Domain
   DateTime? Created
   DateTime? Ended
}

还有一个类图:

class RecordMapping<Record>
{    //simplified and omitted fluff for brevity
     public RecordMapping(ConfigurationElement config)
     {
        //..the set up of the mapping...
     }
}

然后像这样使用它们:

public ProcessFile(...)
{
  ...
  using(var reader = StreamReader(...))
  using(var csvReader = new CsvReader(reader))
  using(var errorWriter = new StreamWriter(...))
  {
      csvReader.Configuration.RegisterClassMap(new RadekMapping(config));
      
      //...set up of csvReader configuration...

      try
      {
         var records = csvReader.GetRecords<Record>();
      }
      catch (Exception ex)
      {
         //..in case of problems...
      }
      ....
  }
  ....
}

【问题讨论】:

  • 检查this out
  • @Magnetron 我做到了。它没有显示的是一种针对另一个字段进行验证的方法。我需要在同一行中验证一个日期与另一个日期,而我在 csvhelper 的示例或帮助中没有发现这一点。

标签: c# csvhelper


【解决方案1】:

在这种情况下,从 CsvHelper 的角度来看,数据可能是“有效的”,因为它可以读取数据,但由于更复杂的原因(例如无效的日期范围)而无效。

在这种情况下,这可能是一种简单的方法:

public IEnumerable<Thing> ReadThings(TextReader textReader)
{
    var result = new List<Thing>();
    using (var csvReader = new CsvReader(textReader))
    {
        while (csvReader.Read())
        {
            var thing = csvReader.GetRecord<Thing>();
            if (IsThingValid(thing))
                result.Add(thing);
            else
                LogInvalidThing(thing);

        }
    }
    return result;
}

如果您需要记录的是原始文本,那就是:

LogInvalidRow(csvReader.Context.RawRecord);

另一种选择——也许是更好的选择——可能是将验证与阅读完全分开。换句话说,只读取没有验证的记录。

var records = csvReaader.GetRecords<Record>(); 

您的阅读器类返回它们而不负责确定哪些是有效的 以及如何处理它们。

然后另一个类可以验证IEnumerable&lt;Record&gt;,返回有效行并记录无效行。

这样,验证和日志记录的逻辑就不会与读取代码相关联。如果您从 CSV 文件以外的其他文件中获取 Record 的集合,它将更容易测试并且更容易重复使用。

【讨论】:

  • 谢谢。我将使用第一种方法。第二种方法对我来说实际上是不可能的,因为如果该行由于逻辑原因无效,我需要保留未处理的行并将其记录在错误文件中......
  • 要获得完整的“原始”行,您可以在读取循环中访问csvReader.Context.RawRecord,然后再调用GetRecord()
  • csvReader.Context.RawRecord 在 csvhelper 版本 20 中已更改为 csvReader.RawRecord
猜你喜欢
  • 2021-12-12
  • 1970-01-01
  • 1970-01-01
  • 2015-06-29
  • 1970-01-01
  • 1970-01-01
  • 2014-01-21
  • 2016-08-04
相关资源
最近更新 更多