web-dev-qa-db-ja.com

CsvHelperでの不正なCSVレコードの処理

CSVファイル内のすべてのレコードを反復処理し、すべての良いレコードを1つのコレクションに追加して、すべての「悪い」レコードを個別に処理できるようにしたいと思います。私はこれを行うことができないようで、私は何かが欠けているに違いないと思います。

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);
    }
}

説明されている他のオプションは、BadDataFoundコールバックアクションを設定して処理することです-

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

しかし、コールバックは呼び出されますが、悪いレコードはまだ私の「良いリスト」になります

リストに追加する前に、レコードが適切かどうかを確認するためにリーダーにクエリを実行する方法はありますか?

この例では、私のレコード定義は-

class Record
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
}

そしてデータ(最初の行は悪い、2番目の行は良い)-

"Jo"hn","Doe",43
"Jane","Doe",21

興味深いことに、MissingFieldExceptionを使用して欠落しているフィールドを処理することは、私が望むとおりに機能しているようです。例外はスローされますが、後続の行は引き続き正常に読み取られます。

7
Zak

これが 私が提供したものです。

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; }
}
8
Josh Close