在CsvHelper中处理错误的CSV记录

Zak*_*Zak 7 c# csv csvhelper

我希望能够遍历CSV文件中的所有记录,并将所有好的记录添加到一个集合中,并分别处理所有“坏的”记录。我似乎无法做到这一点,我想我一定很想念。

如果我尝试捕获BadDataException,则后续读取将失败,这意味着我无法继续读取该文件的其余部分-

while (true)
{
    try
    {
        if (!reader.Read())
            break;

        var record = reader.GetRecord<Record>();
        goodList.Add(record);
    }
    catch (BadDataException ex)
    {
        // Exception is caught but I won't be able to read further rows in file
        // (all further reader.Read() result in same exception thrown)
        Console.WriteLine(ex.Message);
    }
}
Run Code Online (Sandbox Code Playgroud)

讨论的另一个选项是设置BadDataFound回调操作来处理它-

reader.Configuration.BadDataFound = x =>
{
    Console.WriteLine($"Bad data: <{x.RawRecord}>");
};
Run Code Online (Sandbox Code Playgroud)

但是,尽管称为回调,但不良记录仍然会出现在我的“良好列表”中

在将其添加到列表之前,有什么方法可以查询读者以查看记录是否良好?

对于此示例,我的记录定义为-

class Record
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

和数据(第一行坏,第二行好)-

"Jo"hn","Doe",43
"Jane","Doe",21
Run Code Online (Sandbox Code Playgroud)

有趣的是,使用MissingFieldException处理丢失的字段似乎完全按照我的意愿运行-引发了异常,但后续行仍然可以正常读取。

Jos*_*ose 8

这是我提供的示例

void Main()
{
    using (var stream = new MemoryStream())
    using (var writer = new StreamWriter(stream))
    using (var reader = new StreamReader(stream))
    using (var csv = new CsvReader(reader))
    {
        writer.WriteLine("FirstName,LastName");
        writer.WriteLine("\"Jon\"hn\"\",\"Doe\"");
        writer.WriteLine("\"Jane\",\"Doe\"");
        writer.Flush();
        stream.Position = 0;

        var good = new List<Test>();
        var bad = new List<string>();
        var isRecordBad = false;
        csv.Configuration.BadDataFound = context =>
        {
            isRecordBad = true;
            bad.Add(context.RawRecord);
        };
        while (csv.Read())
        {
            var record = csv.GetRecord<Test>();
            if (!isRecordBad)
            {
                good.Add(record);
            }

            isRecordBad = false;
        }

        good.Dump();
        bad.Dump();
    }
}

public class Test
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

  • 这在 2021 年的 CsvHelp 中似乎不再起作用。 csv.Configuration.BadDataFound = context ... 行抛出只读属性。看起来曾经友好的 CsvHelp 库现在处理起来更加复杂。我开始认为编写自己的解析器会比尝试理解如何防止 CSVHelp 抛出 BadData 异常要少一些工作。 (3认同)
  • @FidelOrozco 配置更改为只读以避免线程问题。您只需要创建一个配置并将其传递到构造函数中。更改位于更改日志中,并且更新了文档以反映这一点。我不能指望更新每个堆栈溢出问题,但当我遇到它们时我会更新。如果你想自己写,那就太棒了!将其提交进行速度测试。https://www.joelverhagen.com/blog/2020/12/fastest-net-csv-parsers 他将来还会添加兼容性测试。 (3认同)