首页 > 解决方案 > CsvHelper - 验证整行

问题描述

问题

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

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

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

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

我基本上可以得到的是一种将整个原始行与解析数据一起保留的方法,但是在原始数据仍然可用的情况下验证整行的方法会更好。


问题

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

如果没有,有没有办法将整个 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...
      }
      ....
  }
  ....
}

标签: c#csvhelper

解决方案


在这种情况下,从 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<Record>,返回有效行并记录无效行。

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


推荐阅读