2014-11-06 4 views
14

다양한 데이터 (datetime, decimal)의 목록이있는 CSV 파일이 있습니다. CSV의 샘플 행 :개체 목록에 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>(); 

각 속성을 지정 적절하게 (즉, 날짜, 개방, 높은) 내 목록 values로 CSV의 각 라인을 읽고 할 수있는 간단한 방법이 있을까요?

+0

'TextFieldParser' 클래스가'Microsoft.VisualBasic.FileIO' 네임 스페이스에 숨겨져 있습니다. VisualBasic은 C#에서도 사용할 수 있습니다. – cost

+0

Linq 통해이 작업을 수행 할 -이 게시물을 참조하십시오 : http://stackoverflow.com/questions/3497699/csv-to-object-model-mapping – Kevin

+0

@ 케빈 그 완전히 CSV 사양을 따르지 않습니다. 데이터 내에 쉼표가 포함 된 데이터가있는 경우 문제가 발생합니다. – cost

답변

34

왜 이것을 명시 적으로 해석하지 않습니까? 제한된 수의 속성이 있으므로 그리 어렵지 않습니다. 많은 인수를 요구하는 생성자를 사용하는 대신 반환 유형으로 새로운 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를 사용하여 각 줄을 선택하고 FromCsv 메서드를 사용하여 새로운 DailyValues 인스턴스를 만듭니다. 그러면 System.Collections.Generic.IEnumerable<CsvDemo.DailyValues> 유형이 생성됩니다.
  • 마지막으로 .ToList()IEnumerableList으로 바꾸어 원하는 유형과 일치시킵니다. 대신 당신은 단순히 목록에 각 DailyValues 인스턴스를 추가 할 foreach 루프를 사용할 수도 Linq를 사용의

.

+0

필자는이 접근법을 좋아하며, 필요한 경우 FromCsv에서 더 복잡한 CSV 구문 분석을 구현할 수 있습니다. +1 – Kevin

+0

이것은 stackoverflow에서 제공되는 다른 솔루션보다 훨씬 간단합니다 :) –

+1

간단하고 효율적! +1 – anil