Strongly typed parsing of CSV-files












2














So after about an hour's worth of pulling my hair in desperation, I decided to follow the advice from, like, everybody in here and not implement my own CSV-parser.



So I went with FileHelpers instead.



But I am having a bit of trouble using it correctly.



My CSV-file looks something like this:



50382018,50319368,eBusiness Manager,IT02,3350_FIB4,IT,2480
50370383,50373053,CRM Manager,IT01,3200_FIB3,xyz,2480
50320067,50341107,"VP, Business Information Officer",IT03,3200_FI89,xyz,2480
50299061,50350088,Project Expert,IT02,8118_FI09,abc,2480


My need for FileHelpers (and, specifically CsvEngine) is in line 3 - notice third column enclosed in quotes since it has an internal comma (which is otherwise used as delimiter).



My code to read the file is this:



var co = new FileHelpers.Options.CsvOptions("Employee", columnDeliminator, 7);
var ce = new CsvEngine(co);

var records = ce.ReadFile(pathToCSVFile);


It works fine - sort of. It correctly parses the lines and recognizes the values with enclosed delimiters.



But.



The return value of the ReadFile()-method is object. And the contents of it appears to be some kind of dynamic type.



It looks something like this - where the columns are named "Field_1", "Field_2" etc.



Automatically generated return type



I have created a "data class" intended to hold the parsed lines It looks like this:



public class Employee
{
public string DepartmentPosition;
public string ParentDepartmentPosition;
public string JobTitle;
public string Role;
public string Location;
public string NameLocation;
public string EmployeeStatus;
}


Is there a way to have FileHelpers' CsvEngine class to return strongly typed data?



If I could just use the "basic" parser of FileHelpers, I could use this code:



var engine = new FileHelperEngine<Employee>();
var records = engine.ReadFile("Input.txt");


Is there a way to have CsvEngine return instances of my "Employee" class? Or do I have to write my own mapping code to support this?










share|improve this question






















  • Will the CSV file have headers? Have you looked at using CsvHelper?
    – Nkosi
    Nov 11 at 22:44
















2














So after about an hour's worth of pulling my hair in desperation, I decided to follow the advice from, like, everybody in here and not implement my own CSV-parser.



So I went with FileHelpers instead.



But I am having a bit of trouble using it correctly.



My CSV-file looks something like this:



50382018,50319368,eBusiness Manager,IT02,3350_FIB4,IT,2480
50370383,50373053,CRM Manager,IT01,3200_FIB3,xyz,2480
50320067,50341107,"VP, Business Information Officer",IT03,3200_FI89,xyz,2480
50299061,50350088,Project Expert,IT02,8118_FI09,abc,2480


My need for FileHelpers (and, specifically CsvEngine) is in line 3 - notice third column enclosed in quotes since it has an internal comma (which is otherwise used as delimiter).



My code to read the file is this:



var co = new FileHelpers.Options.CsvOptions("Employee", columnDeliminator, 7);
var ce = new CsvEngine(co);

var records = ce.ReadFile(pathToCSVFile);


It works fine - sort of. It correctly parses the lines and recognizes the values with enclosed delimiters.



But.



The return value of the ReadFile()-method is object. And the contents of it appears to be some kind of dynamic type.



It looks something like this - where the columns are named "Field_1", "Field_2" etc.



Automatically generated return type



I have created a "data class" intended to hold the parsed lines It looks like this:



public class Employee
{
public string DepartmentPosition;
public string ParentDepartmentPosition;
public string JobTitle;
public string Role;
public string Location;
public string NameLocation;
public string EmployeeStatus;
}


Is there a way to have FileHelpers' CsvEngine class to return strongly typed data?



If I could just use the "basic" parser of FileHelpers, I could use this code:



var engine = new FileHelperEngine<Employee>();
var records = engine.ReadFile("Input.txt");


Is there a way to have CsvEngine return instances of my "Employee" class? Or do I have to write my own mapping code to support this?










share|improve this question






















  • Will the CSV file have headers? Have you looked at using CsvHelper?
    – Nkosi
    Nov 11 at 22:44














2












2








2


0





So after about an hour's worth of pulling my hair in desperation, I decided to follow the advice from, like, everybody in here and not implement my own CSV-parser.



So I went with FileHelpers instead.



But I am having a bit of trouble using it correctly.



My CSV-file looks something like this:



50382018,50319368,eBusiness Manager,IT02,3350_FIB4,IT,2480
50370383,50373053,CRM Manager,IT01,3200_FIB3,xyz,2480
50320067,50341107,"VP, Business Information Officer",IT03,3200_FI89,xyz,2480
50299061,50350088,Project Expert,IT02,8118_FI09,abc,2480


My need for FileHelpers (and, specifically CsvEngine) is in line 3 - notice third column enclosed in quotes since it has an internal comma (which is otherwise used as delimiter).



My code to read the file is this:



var co = new FileHelpers.Options.CsvOptions("Employee", columnDeliminator, 7);
var ce = new CsvEngine(co);

var records = ce.ReadFile(pathToCSVFile);


It works fine - sort of. It correctly parses the lines and recognizes the values with enclosed delimiters.



But.



The return value of the ReadFile()-method is object. And the contents of it appears to be some kind of dynamic type.



It looks something like this - where the columns are named "Field_1", "Field_2" etc.



Automatically generated return type



I have created a "data class" intended to hold the parsed lines It looks like this:



public class Employee
{
public string DepartmentPosition;
public string ParentDepartmentPosition;
public string JobTitle;
public string Role;
public string Location;
public string NameLocation;
public string EmployeeStatus;
}


Is there a way to have FileHelpers' CsvEngine class to return strongly typed data?



If I could just use the "basic" parser of FileHelpers, I could use this code:



var engine = new FileHelperEngine<Employee>();
var records = engine.ReadFile("Input.txt");


Is there a way to have CsvEngine return instances of my "Employee" class? Or do I have to write my own mapping code to support this?










share|improve this question













So after about an hour's worth of pulling my hair in desperation, I decided to follow the advice from, like, everybody in here and not implement my own CSV-parser.



So I went with FileHelpers instead.



But I am having a bit of trouble using it correctly.



My CSV-file looks something like this:



50382018,50319368,eBusiness Manager,IT02,3350_FIB4,IT,2480
50370383,50373053,CRM Manager,IT01,3200_FIB3,xyz,2480
50320067,50341107,"VP, Business Information Officer",IT03,3200_FI89,xyz,2480
50299061,50350088,Project Expert,IT02,8118_FI09,abc,2480


My need for FileHelpers (and, specifically CsvEngine) is in line 3 - notice third column enclosed in quotes since it has an internal comma (which is otherwise used as delimiter).



My code to read the file is this:



var co = new FileHelpers.Options.CsvOptions("Employee", columnDeliminator, 7);
var ce = new CsvEngine(co);

var records = ce.ReadFile(pathToCSVFile);


It works fine - sort of. It correctly parses the lines and recognizes the values with enclosed delimiters.



But.



The return value of the ReadFile()-method is object. And the contents of it appears to be some kind of dynamic type.



It looks something like this - where the columns are named "Field_1", "Field_2" etc.



Automatically generated return type



I have created a "data class" intended to hold the parsed lines It looks like this:



public class Employee
{
public string DepartmentPosition;
public string ParentDepartmentPosition;
public string JobTitle;
public string Role;
public string Location;
public string NameLocation;
public string EmployeeStatus;
}


Is there a way to have FileHelpers' CsvEngine class to return strongly typed data?



If I could just use the "basic" parser of FileHelpers, I could use this code:



var engine = new FileHelperEngine<Employee>();
var records = engine.ReadFile("Input.txt");


Is there a way to have CsvEngine return instances of my "Employee" class? Or do I have to write my own mapping code to support this?







c# csv text-parsing filehelpers






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 11 at 16:46









Jesper Lund Stocholm

87221229




87221229












  • Will the CSV file have headers? Have you looked at using CsvHelper?
    – Nkosi
    Nov 11 at 22:44


















  • Will the CSV file have headers? Have you looked at using CsvHelper?
    – Nkosi
    Nov 11 at 22:44
















Will the CSV file have headers? Have you looked at using CsvHelper?
– Nkosi
Nov 11 at 22:44




Will the CSV file have headers? Have you looked at using CsvHelper?
– Nkosi
Nov 11 at 22:44












4 Answers
4






active

oldest

votes


















0














The documentation worked for me for a one simple way:



First in your class, it needs a couple decorators:



Edit Use the FieldQuoted decorator to parse anything in quotes and ignore the included comma



[DelimitedRecord(",")]
class Person
{
[FieldQuoted]
public string Name { get; set; }

[FieldConverter(ConverterKind.Int32)]
public int Age { get; set; }

public string State { get; set; }
}


DelimitedRecord for the class and the expected delimiter (this could be a problem if things change later.



and FieldConverter for it appears anything other than string.



Then change your reading method slightly:



var fhr = new FileHelperEngine<Person>();            
var readLines = fhr.ReadFile(pathToFile);


and then it works, strongly typed:



foreach(var person in readLines)
{
Console.WriteLine(person.Name);
}





share|improve this answer























  • Hi @Austin, you realize that you are suggesting that I try something, that I specifically wrote in my question as not being possible? 😀.
    – Jesper Lund Stocholm
    Nov 11 at 19:22






  • 2




    @Austin's answer looks correct to me. If you want the engine to return an array of concrete classes, you cannot use CsvEngine. You would need to do the mapping yourself. Using FileHelperEngine<Employee> is the best approach, but you need to decorate the class with [DelimitedRecord(",")] and decorate the JobTitle property with [FieldQuoted(QuoteMode.OptionalForRead)].
    – shamp00
    Nov 11 at 20:22










  • Out of curiosity, @JesperLundStocholm why does that not work as a solution? Also, I tried to guess why it didn't, the "Quoted word, with comma" in which case I showed how to get around that.
    – Austin T French
    Nov 11 at 21:07










  • @AustinTFrench I cannot use your suggestion since it chokes on line three with the enclosed delimiter. However - I found the solution and managed to augment your suggestion. See below :-)
    – Jesper Lund Stocholm
    Nov 12 at 21:07










  • Odd, the enclosed delimiter worked fine for me with the update from yesterday...
    – Austin T French
    Nov 12 at 23:02



















0














Using CsvHelper as a viable alternative and assuming the CSV file has no headers,



a mapping can be created for the Employee class like



public sealed class EmployeeClassMap : ClassMap<Employee> {
public EmployeeClassMap() {
Map(_ => _.Location).Index(0);
Map(_ => _.NameLocation).Index(1);
Map(_ => _.JobTitle).Index(2);
//...removed for brevity
}
}


Where the index is mapped to a respective property on the strongly typed object model.



To use this mapping, you need to register the mapping in the configuration.



using (var textReader = new StreamReader(pathToCSVFile)) {
var csv = new CsvReader(textReader);
csv.Configuration.RegisterClassMap<EmployeeClassMap>();

var records = csv.GetRecords<Employee>();

//...
}





share|improve this answer





























    0














    @shamp00 has the correct answer - and I also found it at FileHelper escape delimiter .



    I took my model class and decorated each property on it as suggested:



    (I probably don't need to decorate all properties, but it works for now)



    [DelimitedRecord((","))]
    public class Employee
    {
    [FieldQuoted('"', QuoteMode.OptionalForBoth)]
    public string DepartmentPosition;
    [FieldQuoted('"', QuoteMode.OptionalForBoth)]
    public string ParentDepartmentPosition;
    [FieldQuoted('"', QuoteMode.OptionalForBoth)]
    public string JobTitle;
    [FieldQuoted('"', QuoteMode.OptionalForBoth)]
    public string Role;
    [FieldQuoted('"', QuoteMode.OptionalForBoth)]
    public string Location;
    [FieldQuoted('"', QuoteMode.OptionalForBoth)]
    public string NameLocation;
    [FieldQuoted('"', QuoteMode.OptionalForBoth)]
    public string EmployeeStatus;
    }


    Now I just need this code:



    TextReader reader = new StreamReader(contents);
    var engine = new FileHelperEngine<Employee>()
    {
    Options = { IgnoreFirstLines = 1 }
    };
    var myRecords = engine.ReadStream(reader);





    share|improve this answer





























      -1














      If this lib not work, you can also try to use built-in .Net CSV parser TextFieldParser. For ex: https://coding.abel.nu/2012/06/built-in-net-csv-parser/



      ADDED:
      For types (with auto convert):



          static void run()
      {
      // split with any lib line of CSV
      string line = new string{"john", "doe", "201"};
      // needed prop names of class
      string propNames = "fname|lname|room".Split('|');

      Person p = new Person();
      parseLine<Person>(p, line, propNames);
      }

      static void parseLine<T>(T t, string line, string propNames)
      {
      for(int i = 0;i<propNames.Length;i++)
      {
      string sprop = propNames[i];
      PropertyInfo prop = t.GetType().GetProperty(sprop);
      object val = Convert.ChangeType(line[i], prop.PropertyType);
      prop.SetValue(t, val );
      }
      }

      class Person
      {
      public string fname{get;set;}
      public string lname{get;set;}
      public int room {get;set;}
      }





      share|improve this answer























      • This really is a comment, not much of answer (or maybe a link only answer)
        – Austin T French
        Nov 11 at 18:12










      • can't write comments :(
        – AndrewF
        Nov 11 at 18:14











      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53250936%2fstrongly-typed-parsing-of-csv-files%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      4 Answers
      4






      active

      oldest

      votes








      4 Answers
      4






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      0














      The documentation worked for me for a one simple way:



      First in your class, it needs a couple decorators:



      Edit Use the FieldQuoted decorator to parse anything in quotes and ignore the included comma



      [DelimitedRecord(",")]
      class Person
      {
      [FieldQuoted]
      public string Name { get; set; }

      [FieldConverter(ConverterKind.Int32)]
      public int Age { get; set; }

      public string State { get; set; }
      }


      DelimitedRecord for the class and the expected delimiter (this could be a problem if things change later.



      and FieldConverter for it appears anything other than string.



      Then change your reading method slightly:



      var fhr = new FileHelperEngine<Person>();            
      var readLines = fhr.ReadFile(pathToFile);


      and then it works, strongly typed:



      foreach(var person in readLines)
      {
      Console.WriteLine(person.Name);
      }





      share|improve this answer























      • Hi @Austin, you realize that you are suggesting that I try something, that I specifically wrote in my question as not being possible? 😀.
        – Jesper Lund Stocholm
        Nov 11 at 19:22






      • 2




        @Austin's answer looks correct to me. If you want the engine to return an array of concrete classes, you cannot use CsvEngine. You would need to do the mapping yourself. Using FileHelperEngine<Employee> is the best approach, but you need to decorate the class with [DelimitedRecord(",")] and decorate the JobTitle property with [FieldQuoted(QuoteMode.OptionalForRead)].
        – shamp00
        Nov 11 at 20:22










      • Out of curiosity, @JesperLundStocholm why does that not work as a solution? Also, I tried to guess why it didn't, the "Quoted word, with comma" in which case I showed how to get around that.
        – Austin T French
        Nov 11 at 21:07










      • @AustinTFrench I cannot use your suggestion since it chokes on line three with the enclosed delimiter. However - I found the solution and managed to augment your suggestion. See below :-)
        – Jesper Lund Stocholm
        Nov 12 at 21:07










      • Odd, the enclosed delimiter worked fine for me with the update from yesterday...
        – Austin T French
        Nov 12 at 23:02
















      0














      The documentation worked for me for a one simple way:



      First in your class, it needs a couple decorators:



      Edit Use the FieldQuoted decorator to parse anything in quotes and ignore the included comma



      [DelimitedRecord(",")]
      class Person
      {
      [FieldQuoted]
      public string Name { get; set; }

      [FieldConverter(ConverterKind.Int32)]
      public int Age { get; set; }

      public string State { get; set; }
      }


      DelimitedRecord for the class and the expected delimiter (this could be a problem if things change later.



      and FieldConverter for it appears anything other than string.



      Then change your reading method slightly:



      var fhr = new FileHelperEngine<Person>();            
      var readLines = fhr.ReadFile(pathToFile);


      and then it works, strongly typed:



      foreach(var person in readLines)
      {
      Console.WriteLine(person.Name);
      }





      share|improve this answer























      • Hi @Austin, you realize that you are suggesting that I try something, that I specifically wrote in my question as not being possible? 😀.
        – Jesper Lund Stocholm
        Nov 11 at 19:22






      • 2




        @Austin's answer looks correct to me. If you want the engine to return an array of concrete classes, you cannot use CsvEngine. You would need to do the mapping yourself. Using FileHelperEngine<Employee> is the best approach, but you need to decorate the class with [DelimitedRecord(",")] and decorate the JobTitle property with [FieldQuoted(QuoteMode.OptionalForRead)].
        – shamp00
        Nov 11 at 20:22










      • Out of curiosity, @JesperLundStocholm why does that not work as a solution? Also, I tried to guess why it didn't, the "Quoted word, with comma" in which case I showed how to get around that.
        – Austin T French
        Nov 11 at 21:07










      • @AustinTFrench I cannot use your suggestion since it chokes on line three with the enclosed delimiter. However - I found the solution and managed to augment your suggestion. See below :-)
        – Jesper Lund Stocholm
        Nov 12 at 21:07










      • Odd, the enclosed delimiter worked fine for me with the update from yesterday...
        – Austin T French
        Nov 12 at 23:02














      0












      0








      0






      The documentation worked for me for a one simple way:



      First in your class, it needs a couple decorators:



      Edit Use the FieldQuoted decorator to parse anything in quotes and ignore the included comma



      [DelimitedRecord(",")]
      class Person
      {
      [FieldQuoted]
      public string Name { get; set; }

      [FieldConverter(ConverterKind.Int32)]
      public int Age { get; set; }

      public string State { get; set; }
      }


      DelimitedRecord for the class and the expected delimiter (this could be a problem if things change later.



      and FieldConverter for it appears anything other than string.



      Then change your reading method slightly:



      var fhr = new FileHelperEngine<Person>();            
      var readLines = fhr.ReadFile(pathToFile);


      and then it works, strongly typed:



      foreach(var person in readLines)
      {
      Console.WriteLine(person.Name);
      }





      share|improve this answer














      The documentation worked for me for a one simple way:



      First in your class, it needs a couple decorators:



      Edit Use the FieldQuoted decorator to parse anything in quotes and ignore the included comma



      [DelimitedRecord(",")]
      class Person
      {
      [FieldQuoted]
      public string Name { get; set; }

      [FieldConverter(ConverterKind.Int32)]
      public int Age { get; set; }

      public string State { get; set; }
      }


      DelimitedRecord for the class and the expected delimiter (this could be a problem if things change later.



      and FieldConverter for it appears anything other than string.



      Then change your reading method slightly:



      var fhr = new FileHelperEngine<Person>();            
      var readLines = fhr.ReadFile(pathToFile);


      and then it works, strongly typed:



      foreach(var person in readLines)
      {
      Console.WriteLine(person.Name);
      }






      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Nov 11 at 21:05

























      answered Nov 11 at 17:19









      Austin T French

      2,46611328




      2,46611328












      • Hi @Austin, you realize that you are suggesting that I try something, that I specifically wrote in my question as not being possible? 😀.
        – Jesper Lund Stocholm
        Nov 11 at 19:22






      • 2




        @Austin's answer looks correct to me. If you want the engine to return an array of concrete classes, you cannot use CsvEngine. You would need to do the mapping yourself. Using FileHelperEngine<Employee> is the best approach, but you need to decorate the class with [DelimitedRecord(",")] and decorate the JobTitle property with [FieldQuoted(QuoteMode.OptionalForRead)].
        – shamp00
        Nov 11 at 20:22










      • Out of curiosity, @JesperLundStocholm why does that not work as a solution? Also, I tried to guess why it didn't, the "Quoted word, with comma" in which case I showed how to get around that.
        – Austin T French
        Nov 11 at 21:07










      • @AustinTFrench I cannot use your suggestion since it chokes on line three with the enclosed delimiter. However - I found the solution and managed to augment your suggestion. See below :-)
        – Jesper Lund Stocholm
        Nov 12 at 21:07










      • Odd, the enclosed delimiter worked fine for me with the update from yesterday...
        – Austin T French
        Nov 12 at 23:02


















      • Hi @Austin, you realize that you are suggesting that I try something, that I specifically wrote in my question as not being possible? 😀.
        – Jesper Lund Stocholm
        Nov 11 at 19:22






      • 2




        @Austin's answer looks correct to me. If you want the engine to return an array of concrete classes, you cannot use CsvEngine. You would need to do the mapping yourself. Using FileHelperEngine<Employee> is the best approach, but you need to decorate the class with [DelimitedRecord(",")] and decorate the JobTitle property with [FieldQuoted(QuoteMode.OptionalForRead)].
        – shamp00
        Nov 11 at 20:22










      • Out of curiosity, @JesperLundStocholm why does that not work as a solution? Also, I tried to guess why it didn't, the "Quoted word, with comma" in which case I showed how to get around that.
        – Austin T French
        Nov 11 at 21:07










      • @AustinTFrench I cannot use your suggestion since it chokes on line three with the enclosed delimiter. However - I found the solution and managed to augment your suggestion. See below :-)
        – Jesper Lund Stocholm
        Nov 12 at 21:07










      • Odd, the enclosed delimiter worked fine for me with the update from yesterday...
        – Austin T French
        Nov 12 at 23:02
















      Hi @Austin, you realize that you are suggesting that I try something, that I specifically wrote in my question as not being possible? 😀.
      – Jesper Lund Stocholm
      Nov 11 at 19:22




      Hi @Austin, you realize that you are suggesting that I try something, that I specifically wrote in my question as not being possible? 😀.
      – Jesper Lund Stocholm
      Nov 11 at 19:22




      2




      2




      @Austin's answer looks correct to me. If you want the engine to return an array of concrete classes, you cannot use CsvEngine. You would need to do the mapping yourself. Using FileHelperEngine<Employee> is the best approach, but you need to decorate the class with [DelimitedRecord(",")] and decorate the JobTitle property with [FieldQuoted(QuoteMode.OptionalForRead)].
      – shamp00
      Nov 11 at 20:22




      @Austin's answer looks correct to me. If you want the engine to return an array of concrete classes, you cannot use CsvEngine. You would need to do the mapping yourself. Using FileHelperEngine<Employee> is the best approach, but you need to decorate the class with [DelimitedRecord(",")] and decorate the JobTitle property with [FieldQuoted(QuoteMode.OptionalForRead)].
      – shamp00
      Nov 11 at 20:22












      Out of curiosity, @JesperLundStocholm why does that not work as a solution? Also, I tried to guess why it didn't, the "Quoted word, with comma" in which case I showed how to get around that.
      – Austin T French
      Nov 11 at 21:07




      Out of curiosity, @JesperLundStocholm why does that not work as a solution? Also, I tried to guess why it didn't, the "Quoted word, with comma" in which case I showed how to get around that.
      – Austin T French
      Nov 11 at 21:07












      @AustinTFrench I cannot use your suggestion since it chokes on line three with the enclosed delimiter. However - I found the solution and managed to augment your suggestion. See below :-)
      – Jesper Lund Stocholm
      Nov 12 at 21:07




      @AustinTFrench I cannot use your suggestion since it chokes on line three with the enclosed delimiter. However - I found the solution and managed to augment your suggestion. See below :-)
      – Jesper Lund Stocholm
      Nov 12 at 21:07












      Odd, the enclosed delimiter worked fine for me with the update from yesterday...
      – Austin T French
      Nov 12 at 23:02




      Odd, the enclosed delimiter worked fine for me with the update from yesterday...
      – Austin T French
      Nov 12 at 23:02













      0














      Using CsvHelper as a viable alternative and assuming the CSV file has no headers,



      a mapping can be created for the Employee class like



      public sealed class EmployeeClassMap : ClassMap<Employee> {
      public EmployeeClassMap() {
      Map(_ => _.Location).Index(0);
      Map(_ => _.NameLocation).Index(1);
      Map(_ => _.JobTitle).Index(2);
      //...removed for brevity
      }
      }


      Where the index is mapped to a respective property on the strongly typed object model.



      To use this mapping, you need to register the mapping in the configuration.



      using (var textReader = new StreamReader(pathToCSVFile)) {
      var csv = new CsvReader(textReader);
      csv.Configuration.RegisterClassMap<EmployeeClassMap>();

      var records = csv.GetRecords<Employee>();

      //...
      }





      share|improve this answer


























        0














        Using CsvHelper as a viable alternative and assuming the CSV file has no headers,



        a mapping can be created for the Employee class like



        public sealed class EmployeeClassMap : ClassMap<Employee> {
        public EmployeeClassMap() {
        Map(_ => _.Location).Index(0);
        Map(_ => _.NameLocation).Index(1);
        Map(_ => _.JobTitle).Index(2);
        //...removed for brevity
        }
        }


        Where the index is mapped to a respective property on the strongly typed object model.



        To use this mapping, you need to register the mapping in the configuration.



        using (var textReader = new StreamReader(pathToCSVFile)) {
        var csv = new CsvReader(textReader);
        csv.Configuration.RegisterClassMap<EmployeeClassMap>();

        var records = csv.GetRecords<Employee>();

        //...
        }





        share|improve this answer
























          0












          0








          0






          Using CsvHelper as a viable alternative and assuming the CSV file has no headers,



          a mapping can be created for the Employee class like



          public sealed class EmployeeClassMap : ClassMap<Employee> {
          public EmployeeClassMap() {
          Map(_ => _.Location).Index(0);
          Map(_ => _.NameLocation).Index(1);
          Map(_ => _.JobTitle).Index(2);
          //...removed for brevity
          }
          }


          Where the index is mapped to a respective property on the strongly typed object model.



          To use this mapping, you need to register the mapping in the configuration.



          using (var textReader = new StreamReader(pathToCSVFile)) {
          var csv = new CsvReader(textReader);
          csv.Configuration.RegisterClassMap<EmployeeClassMap>();

          var records = csv.GetRecords<Employee>();

          //...
          }





          share|improve this answer












          Using CsvHelper as a viable alternative and assuming the CSV file has no headers,



          a mapping can be created for the Employee class like



          public sealed class EmployeeClassMap : ClassMap<Employee> {
          public EmployeeClassMap() {
          Map(_ => _.Location).Index(0);
          Map(_ => _.NameLocation).Index(1);
          Map(_ => _.JobTitle).Index(2);
          //...removed for brevity
          }
          }


          Where the index is mapped to a respective property on the strongly typed object model.



          To use this mapping, you need to register the mapping in the configuration.



          using (var textReader = new StreamReader(pathToCSVFile)) {
          var csv = new CsvReader(textReader);
          csv.Configuration.RegisterClassMap<EmployeeClassMap>();

          var records = csv.GetRecords<Employee>();

          //...
          }






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 11 at 23:17









          Nkosi

          110k16117184




          110k16117184























              0














              @shamp00 has the correct answer - and I also found it at FileHelper escape delimiter .



              I took my model class and decorated each property on it as suggested:



              (I probably don't need to decorate all properties, but it works for now)



              [DelimitedRecord((","))]
              public class Employee
              {
              [FieldQuoted('"', QuoteMode.OptionalForBoth)]
              public string DepartmentPosition;
              [FieldQuoted('"', QuoteMode.OptionalForBoth)]
              public string ParentDepartmentPosition;
              [FieldQuoted('"', QuoteMode.OptionalForBoth)]
              public string JobTitle;
              [FieldQuoted('"', QuoteMode.OptionalForBoth)]
              public string Role;
              [FieldQuoted('"', QuoteMode.OptionalForBoth)]
              public string Location;
              [FieldQuoted('"', QuoteMode.OptionalForBoth)]
              public string NameLocation;
              [FieldQuoted('"', QuoteMode.OptionalForBoth)]
              public string EmployeeStatus;
              }


              Now I just need this code:



              TextReader reader = new StreamReader(contents);
              var engine = new FileHelperEngine<Employee>()
              {
              Options = { IgnoreFirstLines = 1 }
              };
              var myRecords = engine.ReadStream(reader);





              share|improve this answer


























                0














                @shamp00 has the correct answer - and I also found it at FileHelper escape delimiter .



                I took my model class and decorated each property on it as suggested:



                (I probably don't need to decorate all properties, but it works for now)



                [DelimitedRecord((","))]
                public class Employee
                {
                [FieldQuoted('"', QuoteMode.OptionalForBoth)]
                public string DepartmentPosition;
                [FieldQuoted('"', QuoteMode.OptionalForBoth)]
                public string ParentDepartmentPosition;
                [FieldQuoted('"', QuoteMode.OptionalForBoth)]
                public string JobTitle;
                [FieldQuoted('"', QuoteMode.OptionalForBoth)]
                public string Role;
                [FieldQuoted('"', QuoteMode.OptionalForBoth)]
                public string Location;
                [FieldQuoted('"', QuoteMode.OptionalForBoth)]
                public string NameLocation;
                [FieldQuoted('"', QuoteMode.OptionalForBoth)]
                public string EmployeeStatus;
                }


                Now I just need this code:



                TextReader reader = new StreamReader(contents);
                var engine = new FileHelperEngine<Employee>()
                {
                Options = { IgnoreFirstLines = 1 }
                };
                var myRecords = engine.ReadStream(reader);





                share|improve this answer
























                  0












                  0








                  0






                  @shamp00 has the correct answer - and I also found it at FileHelper escape delimiter .



                  I took my model class and decorated each property on it as suggested:



                  (I probably don't need to decorate all properties, but it works for now)



                  [DelimitedRecord((","))]
                  public class Employee
                  {
                  [FieldQuoted('"', QuoteMode.OptionalForBoth)]
                  public string DepartmentPosition;
                  [FieldQuoted('"', QuoteMode.OptionalForBoth)]
                  public string ParentDepartmentPosition;
                  [FieldQuoted('"', QuoteMode.OptionalForBoth)]
                  public string JobTitle;
                  [FieldQuoted('"', QuoteMode.OptionalForBoth)]
                  public string Role;
                  [FieldQuoted('"', QuoteMode.OptionalForBoth)]
                  public string Location;
                  [FieldQuoted('"', QuoteMode.OptionalForBoth)]
                  public string NameLocation;
                  [FieldQuoted('"', QuoteMode.OptionalForBoth)]
                  public string EmployeeStatus;
                  }


                  Now I just need this code:



                  TextReader reader = new StreamReader(contents);
                  var engine = new FileHelperEngine<Employee>()
                  {
                  Options = { IgnoreFirstLines = 1 }
                  };
                  var myRecords = engine.ReadStream(reader);





                  share|improve this answer












                  @shamp00 has the correct answer - and I also found it at FileHelper escape delimiter .



                  I took my model class and decorated each property on it as suggested:



                  (I probably don't need to decorate all properties, but it works for now)



                  [DelimitedRecord((","))]
                  public class Employee
                  {
                  [FieldQuoted('"', QuoteMode.OptionalForBoth)]
                  public string DepartmentPosition;
                  [FieldQuoted('"', QuoteMode.OptionalForBoth)]
                  public string ParentDepartmentPosition;
                  [FieldQuoted('"', QuoteMode.OptionalForBoth)]
                  public string JobTitle;
                  [FieldQuoted('"', QuoteMode.OptionalForBoth)]
                  public string Role;
                  [FieldQuoted('"', QuoteMode.OptionalForBoth)]
                  public string Location;
                  [FieldQuoted('"', QuoteMode.OptionalForBoth)]
                  public string NameLocation;
                  [FieldQuoted('"', QuoteMode.OptionalForBoth)]
                  public string EmployeeStatus;
                  }


                  Now I just need this code:



                  TextReader reader = new StreamReader(contents);
                  var engine = new FileHelperEngine<Employee>()
                  {
                  Options = { IgnoreFirstLines = 1 }
                  };
                  var myRecords = engine.ReadStream(reader);






                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 12 at 21:13









                  Jesper Lund Stocholm

                  87221229




                  87221229























                      -1














                      If this lib not work, you can also try to use built-in .Net CSV parser TextFieldParser. For ex: https://coding.abel.nu/2012/06/built-in-net-csv-parser/



                      ADDED:
                      For types (with auto convert):



                          static void run()
                      {
                      // split with any lib line of CSV
                      string line = new string{"john", "doe", "201"};
                      // needed prop names of class
                      string propNames = "fname|lname|room".Split('|');

                      Person p = new Person();
                      parseLine<Person>(p, line, propNames);
                      }

                      static void parseLine<T>(T t, string line, string propNames)
                      {
                      for(int i = 0;i<propNames.Length;i++)
                      {
                      string sprop = propNames[i];
                      PropertyInfo prop = t.GetType().GetProperty(sprop);
                      object val = Convert.ChangeType(line[i], prop.PropertyType);
                      prop.SetValue(t, val );
                      }
                      }

                      class Person
                      {
                      public string fname{get;set;}
                      public string lname{get;set;}
                      public int room {get;set;}
                      }





                      share|improve this answer























                      • This really is a comment, not much of answer (or maybe a link only answer)
                        – Austin T French
                        Nov 11 at 18:12










                      • can't write comments :(
                        – AndrewF
                        Nov 11 at 18:14
















                      -1














                      If this lib not work, you can also try to use built-in .Net CSV parser TextFieldParser. For ex: https://coding.abel.nu/2012/06/built-in-net-csv-parser/



                      ADDED:
                      For types (with auto convert):



                          static void run()
                      {
                      // split with any lib line of CSV
                      string line = new string{"john", "doe", "201"};
                      // needed prop names of class
                      string propNames = "fname|lname|room".Split('|');

                      Person p = new Person();
                      parseLine<Person>(p, line, propNames);
                      }

                      static void parseLine<T>(T t, string line, string propNames)
                      {
                      for(int i = 0;i<propNames.Length;i++)
                      {
                      string sprop = propNames[i];
                      PropertyInfo prop = t.GetType().GetProperty(sprop);
                      object val = Convert.ChangeType(line[i], prop.PropertyType);
                      prop.SetValue(t, val );
                      }
                      }

                      class Person
                      {
                      public string fname{get;set;}
                      public string lname{get;set;}
                      public int room {get;set;}
                      }





                      share|improve this answer























                      • This really is a comment, not much of answer (or maybe a link only answer)
                        – Austin T French
                        Nov 11 at 18:12










                      • can't write comments :(
                        – AndrewF
                        Nov 11 at 18:14














                      -1












                      -1








                      -1






                      If this lib not work, you can also try to use built-in .Net CSV parser TextFieldParser. For ex: https://coding.abel.nu/2012/06/built-in-net-csv-parser/



                      ADDED:
                      For types (with auto convert):



                          static void run()
                      {
                      // split with any lib line of CSV
                      string line = new string{"john", "doe", "201"};
                      // needed prop names of class
                      string propNames = "fname|lname|room".Split('|');

                      Person p = new Person();
                      parseLine<Person>(p, line, propNames);
                      }

                      static void parseLine<T>(T t, string line, string propNames)
                      {
                      for(int i = 0;i<propNames.Length;i++)
                      {
                      string sprop = propNames[i];
                      PropertyInfo prop = t.GetType().GetProperty(sprop);
                      object val = Convert.ChangeType(line[i], prop.PropertyType);
                      prop.SetValue(t, val );
                      }
                      }

                      class Person
                      {
                      public string fname{get;set;}
                      public string lname{get;set;}
                      public int room {get;set;}
                      }





                      share|improve this answer














                      If this lib not work, you can also try to use built-in .Net CSV parser TextFieldParser. For ex: https://coding.abel.nu/2012/06/built-in-net-csv-parser/



                      ADDED:
                      For types (with auto convert):



                          static void run()
                      {
                      // split with any lib line of CSV
                      string line = new string{"john", "doe", "201"};
                      // needed prop names of class
                      string propNames = "fname|lname|room".Split('|');

                      Person p = new Person();
                      parseLine<Person>(p, line, propNames);
                      }

                      static void parseLine<T>(T t, string line, string propNames)
                      {
                      for(int i = 0;i<propNames.Length;i++)
                      {
                      string sprop = propNames[i];
                      PropertyInfo prop = t.GetType().GetProperty(sprop);
                      object val = Convert.ChangeType(line[i], prop.PropertyType);
                      prop.SetValue(t, val );
                      }
                      }

                      class Person
                      {
                      public string fname{get;set;}
                      public string lname{get;set;}
                      public int room {get;set;}
                      }






                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited Nov 11 at 21:54

























                      answered Nov 11 at 18:09









                      AndrewF

                      333




                      333












                      • This really is a comment, not much of answer (or maybe a link only answer)
                        – Austin T French
                        Nov 11 at 18:12










                      • can't write comments :(
                        – AndrewF
                        Nov 11 at 18:14


















                      • This really is a comment, not much of answer (or maybe a link only answer)
                        – Austin T French
                        Nov 11 at 18:12










                      • can't write comments :(
                        – AndrewF
                        Nov 11 at 18:14
















                      This really is a comment, not much of answer (or maybe a link only answer)
                      – Austin T French
                      Nov 11 at 18:12




                      This really is a comment, not much of answer (or maybe a link only answer)
                      – Austin T French
                      Nov 11 at 18:12












                      can't write comments :(
                      – AndrewF
                      Nov 11 at 18:14




                      can't write comments :(
                      – AndrewF
                      Nov 11 at 18:14


















                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.





                      Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                      Please pay close attention to the following guidance:


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53250936%2fstrongly-typed-parsing-of-csv-files%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      這個網誌中的熱門文章

                      Xamarin.form Move up view when keyboard appear

                      Post-Redirect-Get with Spring WebFlux and Thymeleaf

                      Anylogic : not able to use stopDelay()