CSV parsing where headers contain spaces with CsvHelper

I have a CSV file with field headers, and some of them contain two or three words, separated by spaces:

Screenshot of the first few rows of a spreadsheet in a spreadsheet application, including headers that contain spaces, as described above.

You can see the headings of the fields that contain spaces in the figure above:
Time of Day, Process Name, and Image Path.

When I tried to read the CSV by calling reader.GetRecords<DataRecord>(); (where DataRecord is the class I defined), I get an error:

TimeOfDay fields do not exist in the CSV file. "*

This is because my DataRecord class cannot contain members with spaces.

How can I use CsvHelper to parse a CSV file?

+14
source share
3 answers

Based on the CsvHelper documentation , we can achieve the desired results in several ways.

1. Ignore spaces in the headers (which, I believe, should easily solve your problem)

In CsvHelper 3 or later PrepareHeaderForMatch use PrepareHeaderForMatch (documented at http://joshclose.imtqy.com/CsvHelper/configuration#headers ) to remove spaces from the headers:

 csv.Configuration.PrepareHeaderForMatch = header => Regex.Replace(header, @"\s", string.Empty) 

In CsvHelper 2, set the flag IgnoreHeaderWhiteSpace which tells the reader to ignore spaces in the headers when matching columns with properties by name.

 reader.Configuration.IgnoreHeaderWhiteSpace = true; 

2. Read by hand

We can read each field manually, for example:

 var reader = new CsvReader(sr); do { reader.Read(); var record=new DataRecord(); record.TimeOfDay=reader.GetField<string>("Time of Day"); record.ProcessName=reader.GetField<string>("Process Name"); record.PID=reader.GetField<string>("PID"); record.Operation=reader.GetField<string>("Operation"); record.Path=reader.GetField<string>("Path"); record.Result=reader.GetField<string>("Result"); record.Detail=reader.GetField<string>("Detail"); record.ImagePath=reader.GetField<string>("Image Path"); } while (!reader.IsRecordEmpty()); 

3. Class mapping:

We can manually map between our class properties and headers in a CSV file using name class mapping as follows:

 public sealed class DataRecordMap:CsvClassMap<DataRecord> { public DataRecordMap() { Map( m => m.TimeOfDay).Name("Time Of Day"); Map( m => m.ProcessName).Name("Process Name"); Map( m => m.PID).Name("PID"); Map( m => m.Operation).Name("Operation"); Map( m => m.Path).Name("Path"); Map( m => m.Result).Name("Result"); Map( m => m.Detail).Name("Detail"); Map( m => m.ImagePath).Name("Image Path"); } } 

Then we must register this using:

 reader.Configuration.RegisterClassMap<DataRecordMap>(); 
+24
source

You need to create a mapping, http://joshclose.imtqy.com/CsvHelper/mapping .

0
source

The library now supports attributes . You would like to use the attribute name .

 public class DataRecord { [Name("Time of Day")] public string TimeOfDay { get; set; } [Name("Process Name")] public string ProcessName { get; set; } public string PID { get; set; } public string Operation { get; set; } public string Path { get; set; } public string Result { get; set; } public string Detail { get; set; } [Name("Image Path")] public string ImagePath { get; set; } public static IEnumerable<DataRecord> ParseDataRecords(Stream file) { using (var sr = new StreamReader(file)) using (var csv = new CsvReader(sr)) { foreach (var record in csv.GetRecords<DataRecord>()) { yield return record; } } } } 
0
source

Source: https://habr.com/ru/post/1206476/


All Articles