How to read a header from a specific line with CsvHelper?

寵の児 提交于 2019-12-12 11:27:53

问题


I'm trying to read a CSV file where header is at row 3:

some crap line
some empty line
COL1,COL2,COl3,...
val1,val2,val3
val1,val2,val3

How do I tell CSVHelper the header is not at the first row?

I tried to skip 2 lines with Read() but the succeeding call to ReadHeader() throws an exception that the header has already been read.

using (var csv = new CsvReader(new StreamReader(stream), csvConfiguration)) {
   csv.Read();
   csv.Read();
   csv.ReadHeader();
   .....

If I set csvConfiguration.HasHeaderRecord to false ReadHeader() fails again.


回答1:


Try this:

using (var reader = new StreamReader(stream)) {
      reader.ReadLine();
      reader.ReadLine();
      using (var csv = new CsvReader(reader)) {                    
          csv.ReadHeader();                    
    }
}



回答2:


This isn't better than Evk's answer, but I was interested.

The CsvConfiguration class appears to have a Func callback named ShouldSkipRecord that can be wired to to implement custom logic.

https://github.com/JoshClose/CsvHelper/tree/master/src/CsvHelper

CsvConfiguration.cs

/// <summary>
/// Gets or sets the callback that will be called to
/// determine whether to skip the given record or not.
/// This overrides the <see cref="SkipEmptyRecords"/> setting.
/// </summary>
public virtual Func<string[], bool> ShouldSkipRecord { get; set; }

CsvReader.cs

/// <summary>
/// Advances the reader to the next record.
/// If HasHeaderRecord is true (true by default), the first record of
/// the CSV file will be automatically read in as the header record
/// and the second record will be returned.
/// </summary>
/// <returns>True if there are more records, otherwise false.</returns>
public virtual bool Read()
{
    if (doneReading)
    {
        throw new CsvReaderException(DoneReadingExceptionMessage);
    }

    if (configuration.HasHeaderRecord && headerRecord == null)
    {
        ReadHeader();
    }

    do
    {
        currentRecord = parser.Read();
    }
    while (ShouldSkipRecord());

    currentIndex = -1;
    hasBeenRead = true;

    if (currentRecord == null)
    {
        doneReading = true;
    }

    return currentRecord != null;
}

/// <summary>
/// Checks if the current record should be skipped or not.
/// </summary>
/// <returns><c>true</c> if the current record should be skipped, <c>false</c> otherwise.</returns>
protected virtual bool ShouldSkipRecord()
{
    if (currentRecord == null)
    {
        return false;
    }

    return configuration.ShouldSkipRecord != null
        ? configuration.ShouldSkipRecord(currentRecord)
        : configuration.SkipEmptyRecords && IsRecordEmpty(false);
}

Unfortunately, it appears that you'd have to set HasHeaderRecord to false, then set it back to true, prior to calling ReadHeaders or calling Read on the third line, because the ShouldSkipRecord logic in Read() is after the ReadHeader() logic.



来源:https://stackoverflow.com/questions/39641220/how-to-read-a-header-from-a-specific-line-with-csvhelper

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!