2014-11-06 22 views
14

Çeşitli verilerin (datetime, decimal) listesiyle birlikte bir CSV dosyasına sahibim. CSV'den örnek satırı:Nesnelerin listesi için CSV'yi okuyun

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 

Satırların her birini okumak istediğim bir nesne listesi oluşturdum. Nesneler için kurucu aşağıdadır, her bir CSV hattındaki alanların her biri burada kullanılır ve atanır.

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>(); 

her özelliğin atamak uygun (yani tarih, açık, yüksek) listemde values içine CSV her satırı okumak ve kolay bir yolu var mı?

+0

'Microsoft.VisualBasic.FileIO' ad alanında gizli bir' TextFieldParser 'sınıfı var. VisualBasic diyor olsa da, C# ile de kullanabilirsiniz. – cost

+0

Bunu Linq üzerinden yapacağım - şu gönderiye bakın: http://stackoverflow.com/questions/3497699/csv-to-object-model-mapping – Kevin

+0

@Kevin Bu, CSV özelliklerine tam olarak uymuyor. – cost

cevap

34

Neden bunları açıkça ayrıştırmıyoruz? Sınırlı sayıda mülkünüz var, bu yüzden çok zor değil. Birçok argüman gerektiren bir kurucu kullanmak yerine, döndürme türünde yeni bir DailyValues örneğini döndüren statik bir yöntem kullandım. Bu tabii ki DateTime.FromBinary vb

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; 
     } 
    } 
} 

benzer, hala bir varsayılan kurucu ekleyebilir ve (siz de bunun için TryParse kullanabilirsiniz) ayrıştırma başarısız olması durumunda istisna durumları eklemek isteyecektir.

  • File.ReadAllLines, tüm satırları CSV dosyasından bir dize dizisine okur.
  • .Skip(1), başlık satırını atlar.
  • .Select(v => DailyValues.FromCsv(v)), her satırı seçmek ve FromCsv yöntemini kullanarak yeni bir DailyValues örneği oluşturmak için Linq kullanır. Bu, System.Collections.Generic.IEnumerable<CsvDemo.DailyValues> türünü oluşturur.
  • Son olarak, .ToList(), IEnumerable numarasını, istediğiniz türle eşleştirmek için List numarasına iletir. Bunun yerine basitçe listenize her DailyValues örneği eklemek için foreach döngü kullanılmış olabilir Linq kullanarak

.

+0

Bu yaklaşımı beğendim ve gerekirse daha karmaşık CSV ayrıştırmalarını FromCsv'de uygulayabilirsiniz. +1 – Kevin

+0

Bu, stackoverflow üzerinde sağlanan diğer herhangi bir çözümden çok daha basittir :) –

+1

Simple and Effective! +1 – anil

İlgili konular