Importing CSV data into C# classes - c#

I know how to read and display a line of a .csv file. Now I would like to parse that file, store its contents in arrays, and use those arrays as values for some classes I created.
I'd like to learn how though.
Here is an example:
basketball,2011/01/28,Rockets,Blazers,98,99
baseball,2011/08/22,Yankees,Redsox,4,3
As you can see, each field is separated by commas. I've created the Basketball.cs and Baseball classes which is an extension of the Sport.cs class, which has the fields:
private string sport;
private string date;
private string team1;
private string team2;
private string score;
I understand that this is simplistic, and that there's better ways of storing this info, i.e. creating classes for each team, making the date a DateType datatype, and more of the same but I'd like to know how to input this information into the classes.
I'm assuming this has something to do with getters and setters... I've also read of dictionaries and collections, but I'd like to start simple by storing them all in arrays... (If that makes sense... Feel free to correct me).
Here is what I have so far. All it does is read the csv and parrot out its contents on the Console:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace Assign01
{
class Program
{
static void Main(string[] args)
{
string line;
FileStream aFile = new FileStream("../../sportsResults.csv", FileMode.Open);
StreamReader sr = new StreamReader(aFile);
// read data in line by line
while ((line = sr.ReadLine()) != null)
{
Console.WriteLine(line);
line = sr.ReadLine();
}
sr.Close();
}
}
}
Help would be much appreciated.

For a resilient, fast, and low effort solution, you can use CsvHelper which handles a lot of code and edge cases and has pretty good documentation
First, install the CsvHelper package on Nuget
a) CSV with Headers
If your csv has headers like this:
sport,date,team 1,team 2,score 1,score 2
basketball,2011/01/28,Rockets,Blazers,98,99
baseball,2011/08/22,Yankees,Redsox,4,3
You can add attributes to your class to map the field names to your class names like this:
public class SportStats
{
[Name("sport")]
public string Sport { get; set; }
[Name("date")]
public DateTime Date { get; set; }
[Name("team 1")]
public string TeamOne { get; set; }
[Name("team 2")]
public string TeamTwo { get; set; }
[Name("score 1")]
public int ScoreOne { get; set; }
[Name("score 2")]
public int ScoreTwo { get; set; }
}
And then invoke like this:
List<SportStats> records;
using (var reader = new StreamReader(#".\stats.csv"))
using (var csv = new CsvReader(reader))
{
records = csv.GetRecords<SportStats>().ToList();
}
b) CSV without Headers
If your csv doesn't have headers like this:
basketball,2011/01/28,Rockets,Blazers,98,99
baseball,2011/08/22,Yankees,Redsox,4,3
You can add attributes to your class and map to the CSV ordinally by position like this:
public class SportStats
{
[Index(0)]
public string Sport { get; set; }
[Index(1)]
public DateTime Date { get; set; }
[Index(2)]
public string TeamOne { get; set; }
[Index(3)]
public string TeamTwo { get; set; }
[Index(4)]
public int ScoreOne { get; set; }
[Index(5)]
public int ScoreTwo { get; set; }
}
And then invoke like this:
List<SportStats> records;
using (var reader = new StreamReader(#".\stats.csv"))
using (var csv = new CsvReader(reader))
{
csv.Configuration.HasHeaderRecord = false;
records = csv.GetRecords<SportStats>().ToList();
}
Further Reading
Reading CSV file and storing values into an array (295🡅)
Parsing CSV files in C#, with header (245🡅)
Import CSV file to strongly typed data structure in .Net (104🡅)
Reading a CSV file in .NET? (45🡅)
Is there a “proper” way to read CSV files (17🡅)
... many more

Creating array to keep the information is not a very good idea, as you don't know how many lines will be in the input file. What would be the initial size of your Array ?? I would advise you to use for example a Generic List to keep the information (E.g. List<>).
You can also add a constructor to your Sport Class that accepts an array (result of the split action as described in above answer.
Additionally you can provide some conversions in the setters
public class Sport
{
private string sport;
private DateTime date;
private string team1;
private string team2;
private string score;
public Sport(string[] csvArray)
{
this.sport = csvArray[0];
this.team1 = csvArray[2];
this.team2 = csvArray[3];
this.date = Convert.ToDateTime(csvArray[1]);
this.score = String.Format("{0}-{1}", csvArray[4], csvArray[5]);
}
Just for simplicity I wrote the Convert Method, but keep in mind this is also not a very safe way unless you are sure that the DateField always contains valid Dates and Score always contains Numeric Values. You can try other safer methods like tryParse or some Exception Handling.
I all honesty, it must add that the above solution is simple (as requested), on a conceptual level I would advise against it. Putting the mapping logic between attributes and the csv-file in the class will make the sports-class too dependent on the file itself and thus less reusable. Any later changes in the file structure should then be reflected in your class and can often be overlooked. Therefore it would be wiser to put your “mapping & conversion” logic in the main program and keep your class a clean as possible
(Changed your "Score" issue by formatting it as 2 strings combined with a hyphen)

splitting the sting into arrays to get the data can be error prone and slow. Try using an OLE data provider to read the CSV as if it were a table in an SQL database, this way you can use a WHERE clause to filter the results.
App.Config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<connectionStrings>
<add name="csv" providerName="System.Data.OleDb" connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source='C:\CsvFolder\';Extended Properties='text;HDR=Yes;FMT=Delimited';" />
</connectionStrings>
</configuration>
program.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.OleDb;
using System.Configuration;
using System.Data;
using System.Data.Common;
namespace CsvImport
{
class Stat
{
public string Sport { get; set; }
public DateTime Date { get; set; }
public string TeamOne { get; set; }
public string TeamTwo { get; set; }
public int Score { get; set; }
}
class Program
{
static void Main(string[] args)
{
ConnectionStringSettings csv = ConfigurationManager.ConnectionStrings["csv"];
List<Stat> stats = new List<Stat>();
using (OleDbConnection cn = new OleDbConnection(csv.ConnectionString))
{
cn.Open();
using (OleDbCommand cmd = cn.CreateCommand())
{
cmd.CommandText = "SELECT * FROM [Stats.csv]";
cmd.CommandType = CommandType.Text;
using (OleDbDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection))
{
int fieldSport = reader.GetOrdinal("sport");
int fieldDate = reader.GetOrdinal("date");
int fieldTeamOne = reader.GetOrdinal("teamone");
int fieldTeamTwo = reader.GetOrdinal("teamtwo");
int fieldScore = reader.GetOrdinal("score");
foreach (DbDataRecord record in reader)
{
stats.Add(new Stat
{
Sport = record.GetString(fieldSport),
Date = record.GetDateTime(fieldDate),
TeamOne = record.GetString(fieldTeamOne),
TeamTwo = record.GetString(fieldTeamTwo),
Score = record.GetInt32(fieldScore)
});
}
}
}
}
foreach (Stat stat in stats)
{
Console.WriteLine("Sport: {0}", stat.Sport);
}
}
}
}
Here's how the csv should look
stats.csv:
sport,date,teamone,teamtwo,score
basketball,28/01/2011,Rockets,Blazers,98
baseball,22/08/2011,Yankees,Redsox,4

While there are a lot of libraries that will make csv reading easy (see: here), all you need to do right now that you have the line, is to split it.
String[] csvFields = line.Split(",");
Now assign each field to the appropriate member
sport = csvFields[0];
date = csvFields[1];
//and so on
This will however overwrite the values each time you read a new line, so you need to pack the values into a class and save the instances of that class to a list.

Linq also has a solution for this and you can define your output as either a List or an Array. In the example below there is a class that as the definition of the data and data types.
var modelData = File.ReadAllLines(dataFile)
.Skip(1)
.Select(x => x.Split(','))
.Select(dataRow => new TestModel
{
Column1 = dataRow[0],
Column2 = dataRow[1],
Column3 = dataRow[2],
Column4 = dataRow[3]
}).ToList(); // Or you can use .ToArray()

// use "Microsoft.VisualBasic.dll"
using System;
using Microsoft.VisualBasic.FileIO;
class Program {
static void Main(string[] args){
using(var csvReader = new TextFieldParser(#"sportsResults.csv")){
csvReader.SetDelimiters(new string[] {","});
string [] fields;
while(!csvReader.EndOfData){
fields = csvReader.ReadFields();
Console.WriteLine(String.Join(",",fields));//replace make instance
}
}
}
}

Below is for newbie and eye catching solution that most newbie like to try and error
please don;t forget to add System.Core.dll in references
Import namespace in your .cs file : using System.Linq;
Perhaps add iterator will be better code
private static IEnumerable<String> GetDataPerLines()
{
FileStream aFile = new FileStream("sportsResults.csv",FileMode.Open);
StreamReader sr = new StreamReader(aFile);
while ((line = sr.ReadLine()) != null)
{
yield return line;
}
sr.Close();
}
static void Main(string[] args)
{
var query = from data in GetDataPerLines()
let splitChr = data.Split(",".ToCharArray())
select new Sport
{
sport = splitChr[0],
date = splitChr[1],.. and so on
}
foreach (var item in query)
{
Console.Writeline(" Sport = {0}, in date when {1}",item.sport,item.date);
}
}
Maybe like this, the sample above is creating your own iteration using yield (please look at MSDN documentation for that) and create collection based on your string.
Let me know if I write the code wrong since I don;t have Visual studio when I write the answer.
For your knowledge, an array one dimension like "Sport[]" will translate into CLR IEnumerable

Related

Deserialize XML into object with dynamic child elements

I'm trying to deserialize some xml into a C# object. The trick is for the most part, I know what this object will look like. However, this is one child that has dynamic elements.
(here is an example)
<measurement>
<Time>2021-02-02</Time>
<ID>1</ID>
<LeftWheel>
<ValuesRead>
<DynamicValue>12.3</DynamicValue>
<DynamicValue2>2.3</DynamicValue2>
<DynamicValue4>1.3</DynamicValue4>
<DynamicValue3>10.3</DynamicValue3>
</ValuesRead>
</LeftWheel>
<RightWheel>
<ValuesRead>
<DynamicValue>12.3</DynamicValue>
<DynamicValue2>2.3</DynamicValue2>
<DynamicValue6>1.3</DynamicValue6>
<DynamicValue10>10.3</DynamicValue10>
</ValuesRead>
</RightWheel>
</measurement>
In this XML, Measurement, Time, and ID are always going to in the object.
The LeftWheel and RightWheel elements are always going to be there with ValuesRead, but the ValuesRead children are dynamic and can be anything.
I have tried making a C# object to reflect most the structure, and then using the XmlSerializer.UnknownElement to pick up the unknown elements in the ValuesRead element, but I cannot link it to the parent above to know if it is on the LeftWheel or RightWheel.
XmlSerializer serializer = new XmlSerializer(typeof(FVISSiteEvent));
serializer.UnknownElement += UnknownElementFound;
Is there a way I can define the LeftWheel and RightWheel classes to be dynamic for the serialization, while having the other classes not dynamic?
You should be able to use the UnknownElementFound event to manually handle these aspects of serialization. See: Serialize XML array of unknown element name
Other options could be to specify the types you expect to see as XmlElementAtrribute decorated properties and they will just be null if they aren’t deserialized.
There’s also the nuclear option of implementing IXmlSerializable in your class and taking full control of the deserialization.
Uses Custom Serializer :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.Linq;
using System.Xml.Schema;
namespace ConsoleApplication16
{
class Program
{
const string INPUT_FILENAME = #"c:\temp\test.xml";
const string OUTPUT_FILENAME = #"c:\temp\test1.xml";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(INPUT_FILENAME);
XmlSerializer serializer = new XmlSerializer(typeof(Measurement));
Measurement measurement = (Measurement)serializer.Deserialize(reader);
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
XmlWriter writer = XmlWriter.Create(OUTPUT_FILENAME,settings);
serializer.Serialize(writer, measurement);
}
}
[XmlRoot("measurement")]
public class Measurement
{
public DateTime Time { get; set; }
public int ID { get; set; }
[XmlArray("LeftWheel")]
[XmlArrayItem("ValuesRead")]
public List<Wheel> leftWheel { get; set; }
[XmlArray("RightWheel")]
[XmlArrayItem("ValuesRead")]
public List<Wheel> rightWheel { get; set; }
}
public class Wheel : IXmlSerializable
{
List<decimal> values { get; set; }
// Xml Serialization Infrastructure
public void WriteXml(XmlWriter writer)
{
int count = 0;
XElement valuesRead = new XElement("ValuesRead");
for (int i = 0; i < values.Count; i++ )
{
valuesRead.Add(new XElement("ValuesRead" + (i == 0? "" : i.ToString()), values[i]));
}
writer.WriteRaw(valuesRead.ToString());
}
public void ReadXml(XmlReader reader)
{
XElement values = (XElement)XElement.ReadFrom(reader);
this.values = values.Elements().Where(x => x.Name.LocalName.StartsWith("DynamicValue")).Select(x => (decimal)x).ToList();
}
public XmlSchema GetSchema()
{
return (null);
}
}
}
Besides using custom Xml serialization to deserialize your xml file, here is one another approach using Cinchoo ETL - an open source library to handle it simple way (those open to try it!)
Define POCO Class
public class Measurement
{
public DateTime Time { get; set; }
public int ID { get; set; }
[ChoXPath("LeftWheel/ValuesRead/*")]
public double[] LeftWheel { get; set; }
[ChoXPath("RightWheel/ValuesRead")]
public dynamic RightWheel { get; set; }
}
Deserialize using ChoETL
using (var r = ChoXmlReader<Measurement>.LoadText(xml)
.WithXPath("/")
)
{
foreach (var rec in r)
rec.Print();
}
Sample fiddle: https://dotnetfiddle.net/KtNvra
Disclaimer: I'm author of this library.
I've managed to resolve this using a dynamic type when deserializing.
When I deserialize ValuesRead, it is a defined as a dynamic type.
When deserialized, it turns into an XmlNode and from there I iterate over the node use the Name and InnerText values to read all the data.

How to store values of different types in a single Structure

I have a text file in that has a list of strings (Example 6|Chicago|Illinois|I-98;I-90). I am trying to create two Classes. One class (CityReader) reads the text file and other file prints it. I declared a class(CityItem) with 4 variables, int population, string city, string state, List<int> Interstates.
In the CityReader class I created a CityItem Object(CIObj) and was able to read the file and delimit it and returning CIObj. But when I access this object from a different class I am only seeing the last line in the text file. This object is not returning all the values.
I realized though I am reading the file in each loop. I am not storing those values and hence the object is holding only the last object.
CityItem Class-----
using System;
using System.Collections.Generic;
using System.Text;
namespace ReadingAtxtFile
{
public class CityItem
{
public int Population { get; set; }
public string City { get; set; }
public string State { get; set; }
public List<int> Interstates = new List<int>();
}
}
CityReader Class-----
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Collections;
namespace ReadingAtxtFile
{
public class CityReader
{
public CityItem ReadCities(string FilePath)
{
CityItem CIObj = new CityItem();
var AllLines = File.ReadAllLines(FilePath, Encoding.UTF8);
try
{
foreach (var item1 in AllLines)
{
string[] EachLine = item1.Split('|');
CIObj.Population = Convert.ToInt32(EachLine[0]);
CIObj.City = EachLine[1];
CIObj.State = EachLine[2];
string[] IStates = EachLine[3].Split(';');
foreach (var item2 in IStates)
{
var IStatesAfterSplit = item2.Split("-");
CIObj.Interstates.Add(Convert.ToInt32(IStatesAfterSplit[1]));
}
}
}
catch (Exception)
{
Console.WriteLine("There is an issue with processing the data");
}
return CIObj;
}
}
}
Input TextFile:
6|Oklahoma City|Oklahoma|I-35;I-44;I-40
6|Boston|Massachusetts|I-90;I-93
8|Columbus|Ohio|I-70;I-71
I am trying to process the text file and print the data as I like. For example. population
Population,
City, State,
Interstates: I-35,I-40,I-45 (Sorted order)
Your ReadCities method needs to return some kind of collection of CityItem objects, not just a single CityItem object. .Net supports various kinds of collections, but a List is probably best for this instance.
Then, after populating your CityItem object, before moving to the next iteration of the loop, add the CityItem object to your List. Something like...
List<CityItem> listOfCityItems = new List<CityItem>();
foreach (var line in AllLines)
{
CityItem ci = new CityITem();
// Populate the properties of ci
listOfCityItems.Add(ci);
}

fetch details from csv file on basis of name search c#

Step 1: I have created a C# application called : Student details
Step 2: Added four TextBoxes and named them as :
Image below to refer:
Studentname.Text
StudentSurname.Text
StudentCity.Text
StudentState.Text
DATA INSIDE CSV FILE
vikas,gadhi,mumbai,maharashtra
prem,yogi,kolkata,maha
roja,goal,orissa,oya
ram,kala,goa,barka
Issue is How do I fetch all the data(surname,city,state) of user prem into above textboxes studentsurname,studentcity,studentstate from csv file when I search the name in textbox 1 => studentname.Text as prem
Below is the Code where I am stuck at return null and code inside Load_Script_Click
void Connection_fetch_details(String searchName)
{
var strLines = File.ReadLines(filePath);
foreach (var line in strLines)
{
if (line.Split(',')[0].Equals(searchName))
{
Connection_fetch_details cd = new Connection_fetch_details()
{
username = line.Split(',')[1]
};
}
}
return;
}
private void Load_Script_Click(object sender, EventArgs e)
{
// load script is button
String con_env = textenv.Text.ToString();
//Address Address = GetAddress("vikas");
//textsurname.text = Address.Surname
Connection_fetch_details cd = Connection_fetch_details(con_env);
textusername.Text = cd.username;
}
==============================================================
Class file name : Address.class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DDL_SCRIPT_GENERATOR
{
public class Connection_fetch_details
{
public string username { get; set; }
}
}
The main problem is that your method is void, which means it doesn't return any value. So even though you may be finding a match, and creating a Connection_fetch_details object, you aren't returning that result back to the calling method.
This will fix that problem:
Connection_fetch_details Connection_fetch_details(String searchName)
{
var strLines = File.ReadLines(filePath);
foreach (var line in strLines)
{
if (line.Split(',')[0].Equals(searchName))
{
Connection_fetch_details cd = new Connection_fetch_details()
{
username = line.Split(',')[1]
};
return cd; //return the object containing the matched username
}
}
return null;
}
Now it will return a Connection_fetch_details object if there is a match, or null if there is no match.
Next, you asked about returning all the fields, not just one. For that you would need to
a) add more properties to your object
b) add more code to populate those properties from the CSV
c) add code to populate the textboxes with the results from the object.
I'm also going to rename "username" to something more relevant, since none of the field names you described in the question match that. I'm also going to rename your class to "Student", and rename your search method, for the same reason.
Here's an example:
Student searchStudent(String searchName)
{
var strLines = File.ReadLines(filePath);
foreach (var line in strLines)
{
var split = line.Split(',');
if (split[0].Equals(searchName))
{
Student s = new Student()
{
firstname = searchName,
surname = split[1],
city = split[2],
state = split[3]
};
return s; //return the object containing the matched name
}
}
return null;
}
private void Load_Script_Click(object sender, EventArgs e)
{
// load script is button
String con_env = textenv.Text.ToString();
//Address Address = GetAddress("vikas");
//textsurname.text = Address.Surname
Student st = searchStudent(con_env);
textsurname.Text = st.surname;
txtcity.Text = st.city;
txtstate.Text = st.state;
}
namespace DDL_SCRIPT_GENERATOR
{
public class Student
{
public string firstname { get; set; }
public string surname { get; set; }
public string city { get; set; }
public string state { get; set; }
}
}
To accomplish your goal you have to further separate your problem in more granular steps and also distinguish between what you show in your UI and what informations you hold in the background in which format.
Create a class with the desired properties
public class Student { public string Name { get; set; } ... }
Learn how to read a csv file into such an object by using an existing library like CsvHelper or CsvReader.
When you have something like List<Student> from this part. Learn how you can visualize such a thing by using some Binding (also depends on the visualization you use Winforms, WPF, etc.).
Depending on the visualization component it already supports filtering or you need to filter by yourself by using e.g. LINQ to get the matching elements students.Where(student => student.Name.StartsWith(search)).
So far a lot of smaller problems which is simply to much to answer in a single one. Please try to break down your problems into smaller ones and search for their solutions. If you get stuck, ask a new question. That's all I can do for you now.

Extracting Data from XML to List<>

I have this XML file:
<?xml version="1.0" encoding="utf-8" ?>
<Record>
<File name="1.mot">
<Line address="040004" data="0720" />
<Line address="040037" data="31" />
<Line address="04004C" data="55AA55AA" />
</File>
<File name="2.mot">
<Line address="00008242" data="06" />
<Line address="00008025" data="AFC8" />
<Line address="00009302" data="476F6C64" />
</File>
</Record>
What I want to do is to extract the information from the XML and convert that to list. Although I kind of don't know where and how to start. I've googled samples, and questions and the code below is what I've managed to construct so far. I'm not even sure if this code is appropriate for what I wanted to happen. This list will be used for some kind of lookup in the program. Like in file 1.mot, program would read 1.mot, read the xml file, parse both files, extract the info from the xml file and then do a search function to verify if the info in the xml exists in 1.mot.
XElement xmlReqs = XElement.Load("XMLFile1.xml");
List<Requirement> reqs = new List<Requirement>();
foreach (var xmlReq in xmlReqs.Elements("File"))
{
string name = xmlReqs.Attribute("name").Value);
List<InfoLine> info = new List<InfoLine>();
foreach (var xmlInfo in xmlReq.Elements("Line"))
{
string address = xmlProduct.Attribute("address").Value;
string data = xmlProduct.Attribute("data").Value;
}
reqs.Add(new Requirement(address, data));
}
A friend of mine suggested something about using int array or string array and then using this reqs.Find(val => val[0]==target) but I'm not sure how to do so. I'm not well-versed with linq, but what I've gathered, it seems to be quite notable and powerful (?).
Anyway, will the code above work? And how do I call the objects from the list to use for the lookup function of the program?
UPDATE:
Program would be reading 1.mot or 2.mot (depending on the user preference, that's why file name in xml needs to be specified) simultaneously (or not) with the xml file.
1.mot file contains:
S0030000FC
S21404000055AA55AA072000010008000938383138D7
S21404001046305730343130302020202027992401B0
...
Address starts at the 3rd byte. So yeah, would be comparing the data to these bunch of lines.
You can de-serialize the xml file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication2
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XmlSerializer xs = new XmlSerializer(typeof(Record));
XmlTextReader reader = new XmlTextReader(FILENAME);
Record record = (Record)xs.Deserialize(reader);
}
}
[XmlRoot("Record")]
public class Record
{
[XmlElement("File")]
public List<File> files {get;set;}
}
[XmlRoot("File")]
public class File
{
[XmlAttribute("name")]
public string name { get; set; }
[XmlElement("Line")]
public List<Line> lines {get;set;}
}
[XmlRoot("Line")]
public class Line
{
[XmlAttribute("address")]
public string address {get;set;}
[XmlAttribute("data")]
public string data {get;set;}
}
}
​
You could use XmlSerializer to handle the reading of the XML. Create some classes that look like these:
public class Record
{
[XmlElement("File")]
public List<File> Files { get; set; }
}
public class File
{
[XmlAttribute("name")]
public string Name { get; set; }
[XmlElement("Line")]
public List<Line> Lines { get; set; }
}
public class Line
{
[XmlAttribute("address")]
public int Address { get; set; }
[XmlAttribute("data")]
public string Data { get; set; }
}
And deserialise like so:
var serializer = new XmlSerializer(typeof (Record));
using (var reader = XmlReader.Create("XMLFile1.xml"))
{
var record = (Record) serializer.Deserialize(reader);
var first = record.Files.Single(f => f.Name == "1.mot");
var second = record.Files.Single(f => f.Name == "2.mot");
}

how to read a CSV file to a List<myClass>?

is it possible to create a List of my own class from a CSV file?
the file e.g. looks like:
ID;NAME
1;Foo
2;Bar
then I have a class like:
class MyClass
{
public int id { get; set; }
public string name { get; set; }
}
is it possible to generate a list of this class out of the cvs file? maybe with some library
You could use a CSV parser such as FileHelpers or FastCSV. If you don't want to use third party libraries you may take a look at the built-in TextFieldParser class which could be used like that:
public IEnumerable<MyClass> Parse(string path)
{
using (TextFieldParser parser = new TextFieldParser(path))
{
parser.CommentTokens = new string[] { "#" };
parser.SetDelimiters(new string[] { ";" });
parser.HasFieldsEnclosedInQuotes = true;
// Skip over header line.
parser.ReadLine();
while (!parser.EndOfData)
{
string[] fields = parser.ReadFields();
yield return new MyClass()
{
id = fields[0],
name = fields[1]
};
}
}
}
and then:
List<MyClass> list = Parse("data.csv").ToList();
But never, please never roll your own CSV parser as other people suggested you here as answers to your question.

Categories

Resources