Подтвердить что ты не робот

Чтение CSV в список объектов

У меня есть CSV файл со списком разнообразных данных (datetime, decimal). Пример строки из CSV:

Date,Open,High,Low,Close,Volume,Adj Close  //I need to skip this first line as well
2012-11-01,77.60,78.12,77.37,78.05,186200,78.05

У меня есть список созданных объектов, которые я хочу прочитать в каждой строке. Конструктор для объектов ниже, каждое из полей из каждой строки CSV используется и назначается здесь.

    public DailyValues(DateTime date, decimal open, decimal high, decimal low,
        decimal close, decimal volume, decimal adjClose)
        : this()
    {
        Date = date;
        Open = open;
        High = high;
        Low = low;
        Close = close;
        Volume = volume;
        AdjClose = adjClose;
    }

    List<DailyValues> values = new List<DailyValues>();

Есть ли простой способ прочитать каждую строку CSV в моем списке values и соответствующим образом назначить каждый атрибут (то есть дату, открыть, высокий)?

4b9b3361

Ответ 1

Почему бы просто не разобрать их явно? У вас ограниченное количество свойств, поэтому это не очень сложно. Вместо использования конструктора, требующего много аргументов, я использовал статический метод, который возвращает новый экземпляр DailyValues в качестве возвращаемого типа. Это похоже на DateTime.FromBinary и т.д.

using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;

namespace CsvDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            List<DailyValues> values = File.ReadAllLines("C:\\Users\\Josh\\Sample.csv")
                                           .Skip(1)
                                           .Select(v => DailyValues.FromCsv(v))
                                           .ToList();
        }
    }

    class DailyValues
    {
        DateTime Date;
        decimal Open;
        decimal High;
        decimal Low;
        decimal Close;
        decimal Volume;
        decimal AdjClose;

        public static DailyValues FromCsv(string csvLine)
        {
            string[] values = csvLine.Split(',');
            DailyValues dailyValues = new DailyValues();
            dailyValues.Date = Convert.ToDateTime(values[0]);
            dailyValues.Open = Convert.ToDecimal(values[1]);
            dailyValues.High = Convert.ToDecimal(values[2]);
            dailyValues.Low = Convert.ToDecimal(values[3]);
            dailyValues.Close = Convert.ToDecimal(values[4]);
            dailyValues.Volume = Convert.ToDecimal(values[5]);
            dailyValues.AdjClose = Convert.ToDecimal(values[6]);
            return dailyValues;
        }
    }
}

Конечно, вы можете добавить конструктор по умолчанию, и вы захотите добавить обработку исключений в случае сбоя синтаксического анализа (вы также можете использовать для этого TryParse).

  • File.ReadAllLines считывает все строки из файла CSV в массив строк.
  • .Skip(1) пропускает строку заголовка.
  • .Select(v => DailyValues.FromCsv(v)) использует Linq для выбора каждой строки и создания нового экземпляра DailyValues с использованием метода FromCsv. Это создает тип System.Collections.Generic.IEnumerable<CsvDemo.DailyValues>.
  • Наконец, .ToList() преобразуйте IEnumerable в List в соответствии с типом, который вы хотите.

Вместо использования Linq вы могли бы просто использовать цикл foreach, чтобы добавить каждый экземпляр DailyValues в ваш список.