Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I pass a collection of strings as a TextReader?

Tags:

c#

stream

csv

I am using the CSVHelper library, which can extract a list of objects from a CSV file with just three lines of code:

var streamReader = // Create a reader to your CSV file.
var csvReader = new CsvReader( streamReader );
List<MyCustomType> myData = csvReader.GetRecords<MyCustomType>();

However, by file has nonsense lines and I need to skip the first ten lines in the file. I thought it would be nice to use LINQ to ensure 'clean' data, and then pass that data to CsvFReader, like so:

public TextReader GetTextReader(IEnumerable<string> lines)
{
    // Some magic here. Don't want to return null;
    return TextReader.Null;
}
public IEnumerable<T> ExtractObjectList<T>(string filePath) where T : class
{
    var csvLines = File.ReadLines(filePath)
                        .Skip(10)
                        .Where(l => !l.StartsWith(",,,"));
    var textReader = GetTextReader(csvLines);
    var csvReader = new CsvReader(textReader);
    csvReader.Configuration.ClassMapping<EventMap, Event>();
    return csvReader.GetRecords<T>();
}

But I'm really stuck into pushing a 'static' collection of strings through a stream like a TextReaer.

My alternative here is to process the CSV file line by line through CsvReader and examine each line before extracting an object, but I find that somewhat clumsy.

like image 706
ProfK Avatar asked Mar 31 '13 06:03

ProfK


2 Answers

The StringReader Class provides a TextReader that wraps a String. You could simply join the lines and wrap them in a StringReader:

public TextReader GetTextReader(IEnumerable<string> lines)
{
    return new StringReader(string.Join("\r\n", lines));
}
like image 56
dtb Avatar answered Oct 22 '22 07:10

dtb


An easier way would be to use CsvHelper to skip the lines.

// Skip rows.
csvReader.Configuration.IgnoreBlankLines = false;
csvReader.Configuration.IgnoreQuotes = true;
for (var i = 0; i < 10; i++)
{
    csvReader.Read();
}
csvReader.Configuration.IgnoreBlankLines = false;
csvReader.Configuration.IgnoreQuotes = false;

// Carry on as normal.
var myData = csvReader.GetRecords<MyCustomType>;

IgnoreBlankLines is turned off in case any of those first 10 rows are blank. IgnoreQuotes is turned off so you don't get any BadDataExceptions if those rows contain a ". You can turn them back on after for normal functionality again.

If you don't know the amount of rows and need to test based on row data, you can just test csvReader.Context.Record and see if you need to stop. In this case, you would probably need to manually call csvReader.ReadHeader() before calling csvReader.GetRecords<MyCustomType>().

like image 45
Josh Close Avatar answered Oct 22 '22 07:10

Josh Close