2011-10-09 101 views
2

我知道如何讀取和顯示.csv文件的一行。現在我想解析該文件,將其內容存儲在數組中,並將這些數組用作我創建的某些類的值。將CSV數據導入到C#類中

我想知道如何。

下面是一個例子:

basketball,2011/01/28,Rockets,Blazers,98,99 
baseball,2011/08/22,Yankees,Redsox,4,3 

正如可以看到的,每個字段由逗號分隔。我創建了Basketball.cs和棒球類這是Sport.cs類的擴展,它具有以下字段:

private string sport; 
private string date; 
private string team1; 
private string team2; 
private string score; 

我明白,這是簡單的,而且還有存儲這些信息的更好的方法,即爲每個團隊創建類,使日期成爲DateType數據類型,以及更多相同的內容,但我想知道如何將這些信息輸入到類中。

我假設這與getter和setters有關...我也讀過字典和集合,但我想通過將它們全部存儲在數組中...(如果有道理......隨時糾正我)。

這是我到目前爲止。它所要做的就是讀取csv和parrot在控制檯上的內容:

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

幫助將不勝感激。

回答

6

創建數組以保留信息不是一個好主意,因爲您不知道將有多少行將在輸入文件。你的數組的初始大小是多少?我建議您使用例如通用列表來保存信息(例如列表<>)。

您還可以添加一個構造函數,如上面的回答描述了接受一個數組(分裂作用的結果,你的體育類。

另外,你可以提供一些轉換的制定者

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

爲了簡單起見,我寫了Convert Method,但請記住,除非您確定DateField始終包含有效日期,Score總是包含Numeric Values,否則這不是一種非常安全的方法。您可以嘗試其他更安全的方法,如tryParse或某些Exception處理。

我所有的誠實,它必須補充說,上述解決方案很簡單(按要求),在概念層面上,我會建議不要這樣做。將屬性與csv文件之間的映射邏輯放在類中會使運動類過於依賴文件本身,因此不易重用。任何後來的文件結構變化都應該反映在你的課堂上,而且經常會被忽視。因此,這將是明智的把你的「映射&轉換」的邏輯在主程序中,並保持你的類清潔儘可能

(改變了你的「分數」的問題被格式化爲2串用連字符組合)

+0

我不會真的把得分作爲一個整數,因爲它是兩個整數相比......即99-98。但我很欣賞這個答案。謝謝。 – iggy2012

3

儘管有許多庫可以讓csv閱讀變得簡單(請參閱:here),但您現在需要做的就是分割它。

String[] csvFields = line.Split(","); 

現在每個字段分配給相應的成員

sport = csvFields[0]; 
date = csvFields[1]; 
//and so on 

這每次讀一個新行時間將然而覆蓋值,所以你需要收拾值成一類,並保存實例這個班級的名單。

+0

當你說包裝值到一個類,並將實例保存到列表中,你究竟是什麼意思? – iggy2012

+1

請參閱用戶936598評論課程的外觀。然後創建一個''''列表 sports = new列表()''''在進入lop之前使用''''sports.Add(new Sport(line.split(「,」)));'' '在while循環中添加它。 – Darcara

0

下面是大多數新手喜歡嘗試和錯誤 請不要新手,醒目的解決方案;別忘了在你的cs文件添加System.Core.dll在引用 導入命名空間:using System.Linq的;

也許添加迭代器將是更好的代碼

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

也許這樣,樣品上面創建一個使用產自己的迭代(請查看MSDN文檔說),並創建集合根據您的字符串。

讓我知道,如果我寫錯了代碼,因爲我沒有;當我寫答案時沒有Visual Studio。 爲了您的所知,像「Sport []」這樣的數組一維將轉化爲CLR IEnumerable

6

將sting分解爲數組以獲取數據可能容易出錯並且速度很慢。嘗試使用OLE數據提供程序來讀取CSV,就好像它是SQL數據庫中的表一樣,這樣您就可以使用WHERE子句來過濾結果。

 
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 stats = new List(); 

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

 

編輯

我忘了展示CSV應該如何看:)

 
stats.csv 

sport,date,teamone,teamtwo,score 
basketball,28/01/2011,Rockets,Blazers,98 
baseball,22/08/2011,Yankees,Redsox,4 
+0

這比我的理解還要進一步,我試着從簡單開始,但我很欣賞它。 – iggy2012

1
// 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 
      } 
     } 
    } 
} 
0

這裏是我做了一個類加載一個逗號分隔的CSV文件導入一個列表<列表< string>>,它實際上是一個數組。

class CSV 
{ 
    public List<List<string>> content = new List<List<string>>(); 
    private string path; 

    public CSV(string path) 
    { 
     this.path = path; 
    } 

    public void Load() 
    { 
     System.IO.StreamReader raw = new System.IO.StreamReader(path); 
     while (!raw.EndOfStream) 
     { 
      string[] tmp = raw.ReadLine().Split(","[0]); 
      content.Add(ArrayToList(tmp)); 
     } 

    } 

    private List<string> ArrayToList(string[] array) 
    { 
     List<string> array_out = new List<string>(); 
     for(int x = 0; x < array.Length; x++) 
     { 
      array_out.Add(array[x]); 
     } 
     return array_out; 
    } 
} 

下面是關於如何使用它的一個例子:

CSV csv = new CSV("C:\file.csv"); //Sets the filename to be used. Can be relative (".\file.csv") 
csv.Load(); //Loads the CSV file into the List<List<string>> 
System.Console.WriteLine(csv.content[row][column]); //Read a cell in the CSV array 

如果你必須使用一個字符串[] [],這裏是轉換列表<列表<字符串>>一種方法一個字符串[] []

public string[][] ListToArray(List<List<string>> list) 
    { 
     string[][] array_out = new string[list.Count][]; 
     for(int x=0; x<list.Count; x++) 
     { 
      for(int y=0; y<list[x].Count; y++) 
      { 
       array_out[x][y] = list[x][y]; 
      } 
     } 
     return array_out; 
    } 

希望這有助於!