BitShift
BitShift

Reputation: 1047

read from csv to object[] C#

I am trying to read from a .csv file to an object array.

There are other solutions here that give solutions for lists but I cannot seem to make it work for me.

Object definition:

public class DTOClass
{
    //declare data members
    [DataMember]
    public DateTime Date { get; set; }
    [DataMember]
    public string stock_symbol { get; set; }
    [DataMember]
    public double stock_price_open { get; set; }
    [DataMember]
    public double stock_price_close { get; set; }
    [DataMember]
    public double stock_price_low { get; set; }
    [DataMember]
    public double stock_price_high { get; set; }
    [DataMember]
    public double stock_price_adj_close { get; set; }
    [DataMember]
    public long stock_volume { get; set; }
    [DataMember]
    public string stock_exchange { get; set; }
}

Instance declaration:

private DTOClass[] _dTOs;

Filter method:

private List<DTOClass> FromCsv(string csvLine, List<DTOClass> rest)
{
    DataTable _dt = new DataTable();

    string[] values = csvLine.Split(',');

    int j = _dt.Rows.Count;
    for (int i = 0; i < j; i++)
    {
        DTOClass dto = new DTOClass();

        dto.Date = Convert.ToDateTime(values[0]);
        dto.stock_symbol = Convert.ToString(values[1]);
        dto.stock_price_open = Convert.ToDouble(values[2]);
        dto.stock_price_close = Convert.ToDouble(values[3]);
        dto.stock_price_low = Convert.ToDouble(values[4]);
        dto.stock_price_high = Convert.ToDouble(values[5]);
        dto.stock_price_adj_close = Convert.ToDouble(values[6]);
        dto.stock_volume = Convert.ToInt64(values[7]);
        dto.stock_exchange = Convert.ToString(values[8]);

        rest.Add(dto);
    }

    return rest;
}

Calling filter:

DTO = File.OpenText(Filename).ReadLine().Select(v => FromCsv(v.ToString(), 
_restDto)).ToArray();

I need this to return to an object array because it then goes into a CollectionView on a datagrid.

But I keep getting this error:

"Cannot implicitly convert type 'System.Collections.Generic.List[]' to 'MBM.Services.DTOClass[]'"

I know that I'm obviously returning a list of a list, but I've tried other methods that are offered and I'm simply stumped.

I've also tried this:

private static DataTable GetDataTableFromCSVFile(string csv_file_path)
{
    DataTable csvData = new DataTable();

    try
    {
        using (TextFieldParser csvReader = new TextFieldParser(csv_file_path))
        {
            csvReader.SetDelimiters(new string[] { "," });
            //csvReader.HasFieldsEnclosedInQuotes = true;
            string[] colFields = csvReader.ReadFields();

            foreach (string column in colFields)
            {
                DataColumn datecolumn = new DataColumn(column);
                datecolumn.AllowDBNull = true;
                csvData.Columns.Add(datecolumn);
            }

            while (!csvReader.EndOfData)
            {
                string[] fieldData = csvReader.ReadFields();
                //Making empty value as null
                for (int i = 0; i < fieldData.Length; i++)
                {
                    if (fieldData[i] == "")
                    {
                        fieldData[i] = null;
                    }
                }

                csvData.Rows.Add(fieldData);
            }
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }

    return csvData;
}

Calling with:

DataTable csvData = GetDataTableFromCSVFile(Filename);

But this doesn't seem to return anything from the file.

Any help is appreciated, thanks.

Upvotes: 2

Views: 8649

Answers (2)

johnny 5
johnny 5

Reputation: 20987

There's no point in recreating the wheel, Id just use CsvHelper, it has support for what you're doing in addition to handling malformed CSV's you can additionally set up mapping like so:

public sealed class MyClassMap : ClassMap<MyClass>
{
    public MyClassMap()
    {
        AutoMap();
        Map( m => m.CreatedDate ).Ignore();
    }
}

Then you can get the object like so:

var csv = new CsvReader( textReader );
var records = csv.GetRecords<MyClass>();

Upvotes: 1

Drag and Drop
Drag and Drop

Reputation: 2734

One simple way will be to split the lines and select them into your new object.

var result = File.ReadAllLines("pathTo.csv")
                .Select(line => line.Split(','))
                .Select(x => new MyObject { 
                    prop1 = x[0],
                    prop2 = x[1],
                    //etc.. 
                })
                .ToArray();

Upvotes: 7

Related Questions