可以Lumenworks CSV解析器错误时,有太多的列在一行

本文关键字:一行 太多 CSV Lumenworks 错误 可以 | 更新日期: 2023-09-27 18:03:59

我使用Lumenworks.Framework.IO.Csv.CsvReader读取Csv文件,并希望检测格式错误的文件。如果一行的列数少于标题,则抛出LumenWorks.Framework.IO.Csv.MissingFieldCsvException。但是,如果一行的列数多于标题,则在解析该行时将其截断。是否有任何属性我可以设置使它抛出?还是另一种高效、易于使用并能检测到此问题的CSV解析器?

我的测试文件看起来像

Field 1,Field 2,Field 3,Field 4
This,data,looks,ok
But,this,has,too,many,fields

我的集成测试(NUnit)看起来像

[Test, ExpectedException(typeof(MalformedCsvException))]
public void Row_cannot_have_more_fields_than_the_header()
{
    using (var stream = File.OpenText("MoreColumnsThanHeader.csv"))
        new CsvParser().ReadCsv(stream);
}

和我的代码读取数据

public DataSubmission ReadCsv(StreamReader streamReader)
{
    var data = new DataSubmission();
    using (var reader = new CsvReader(streamReader, true))
    {
        var items = new List<Row>();
        var fieldCount = reader.FieldCount; //this is 4 in the test
        var headers = reader.GetFieldHeaders();
        while (reader.ReadNextRecord()) //reader has a size 4 array for the 6 item row
            items.Add(ReadRow(fieldCount, headers, reader));
        data.Items = items;
    }
    return data;
}
private static Row ReadRow(int fieldCount, IList<string> headers, CsvReader reader)
{
    var item = new Row();
    var fields = new List<Field>();
    for (var index = 0; index < fieldCount; index++)
        fields.Add(ReadField(headers, reader, index));
    item.Fields = fields;
    return item;
}
private static Field ReadField(IList<string> headers, CsvReader reader, int index)
{
    return new Field {FieldName = headers[index], FieldValue = NullifyEmptyString(reader, index)};
}
private static string NullifyEmptyString(CsvReader reader, int index)
{
    return string.IsNullOrWhiteSpace(reader[index]) ? null : reader[index];
}

编辑:自从创建这个问题,我已经改变了我的CSV解析器使用Microsoft.VisualBasic.FileIO.TextFieldParser。它易于使用,即使处理大文件也表现良好,并且比Lumenworks提供的功能更强大。在处理引号字符串中的换行时,我遇到了Lumenworks解析器的问题。Microsoft解析器可以很好地处理这个问题。

可以Lumenworks CSV解析器错误时,有太多的列在一行

尝试使用来自Mike Stall的DataTable csv reader (nuget csvtools)。

如果在DataTable.New中的任何Read方法中设置了allowMismatch = false,则如果给定行的列数不等于预期的列数,则会抛出异常。

我采用的方法是使用File.ReadAllLines(),然后为每行单独启动CsvReader,并将列数与标题行的列数进行比较。如果有任何带有额外逗号的记录,则列计数将更高。像这样:

var rawRecords = File.ReadAllLines(dataFileName);
foreach (string rawRecord in rawRecords)
{
    using (CsvReader csvRawRecord = new CsvReader(new StringReader(rawRecord), false))
    {
        if (csvRawRecord.FieldCount != fileColumnCount)
        {
            return false;
        }
    }
}

获取ReadRow内部的FieldCount,并将其与头行传递的FieldCount进行检查。