CsvHelper - 验证整行

mis*_*han 0 c# csvhelper

问题

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

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

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

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

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


问题

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

如果没有,有没有办法将整个原始行保存到记录中,以便我可以在解析该行后验证该行,如果它无效,请对它们执行我需要的操作?


我有代码

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

class Record
{  //simplified and omitted fluff for brevity
   string Login
   string Domain
   DateTime? Created
   DateTime? Ended
}
Run Code Online (Sandbox Code Playgroud)

和一个类映射:

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

然后像这样使用它们:

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...
      }
      ....
  }
  ....
}
Run Code Online (Sandbox Code Playgroud)

Sco*_*nen 5

在这种情况下,从 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;
}
Run Code Online (Sandbox Code Playgroud)

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

LogInvalidRow(csvReader.Context.RawRecord);
Run Code Online (Sandbox Code Playgroud)

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

var records = csvReaader.GetRecords<Record>(); 
Run Code Online (Sandbox Code Playgroud)

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

然后另一个类可以验证IEnumerable<Record>,返回有效行并记录无效行。

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

  • 在 csvhelper 版本 20 中,“csvReader.Context.RawRecord”已更改为“csvReader.RawRecord” (2认同)