将CSV数据导入C#类

igg*_*012 4 c# csv import class getter-setter

我知道如何阅读和显示.csv文件的一行.现在我想解析该文件,将其内容存储在数组中,并将这些数组用作我创建的某些类的值.

我想学习如何.

这是一个例子:

basketball,2011/01/28,Rockets,Blazers,98,99
baseball,2011/08/22,Yankees,Redsox,4,3
Run Code Online (Sandbox Code Playgroud)

如您所见,每个字段用逗号分隔.我创建了Basketball.cs和Baseball类,它是Sport.cs类的扩展,它包含以下字段:

private string sport;
private string date;
private string team1;
private string team2;
private string score;
Run Code Online (Sandbox Code Playgroud)

我知道这很简单,并且有更好的方法来存储这些信息,即为每个团队创建类,使日期成为DateType数据类型,以及更多相同但我想知道如何将此信息输入到类.

我假设这与getter和setter有关...我也读过字典和集合,但我想通过将它们全部存储在数组中来开始简单...(如果这有意义.. .随意纠正我).

这是我到目前为止所拥有的.它所做的就是阅读csv并在控制台上鹦鹉学舌:

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

非常感谢帮助.

Kyl*_*Mit 7

对于有弹性、快速和省力的解决方案,您可以使用CsvHelper,它处理大量代码和边缘情况,并有很好的文档

首先,在Nuget 上安装CsvHelper 包

CsvHelper nuget 下载

a)带有标题的CSV

如果您的 csv 有这样的标题:

sport,date,team 1,team 2,score 1,score 2
basketball,2011/01/28,Rockets,Blazers,98,99
baseball,2011/08/22,Yankees,Redsox,4,3
Run Code Online (Sandbox Code Playgroud)

您可以向类添加属性以将字段名称映射到类名称,如下所示:

public class SportStats
{
    [Name("sport")]
    public string Sport { get; set; }
    [Name("date")]
    public DateTime Date { get; set; }
    [Name("team 1")]
    public string TeamOne { get; set; }
    [Name("team 2")]
    public string TeamTwo { get; set; }
    [Name("score 1")]
    public int ScoreOne { get; set; }
    [Name("score 2")]
    public int ScoreTwo { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

然后像这样调用:

List<SportStats> records;

using (var reader = new StreamReader(@".\stats.csv"))
using (var csv = new CsvReader(reader))
{
    records = csv.GetRecords<SportStats>().ToList();
}
Run Code Online (Sandbox Code Playgroud)

b)没有标题的CSV

如果您的 csv 没有这样的标题:

List<SportStats> records;

using (var reader = new StreamReader(@".\stats.csv"))
using (var csv = new CsvReader(reader))
{
    records = csv.GetRecords<SportStats>().ToList();
}
Run Code Online (Sandbox Code Playgroud)

您可以将属性添加到您的类并按如下位置顺序映射到 CSV:

basketball,2011/01/28,Rockets,Blazers,98,99
baseball,2011/08/22,Yankees,Redsox,4,3
Run Code Online (Sandbox Code Playgroud)

然后像这样调用:

List<SportStats> records;

using (var reader = new StreamReader(@".\stats.csv"))
using (var csv = new CsvReader(reader))
{
    csv.Configuration.HasHeaderRecord = false;
    records = csv.GetRecords<SportStats>().ToList();
}
Run Code Online (Sandbox Code Playgroud)

进一步阅读


taz*_*vel 6

创建数组以保存信息不是一个好主意,因为您不知道输入文件中将有多少行.你的数组的初始大小是多少?我建议你使用例如通用列表来保存信息(例如List <>).

您还可以向接受数组的Sport Class添加构造函数(如上面的答案中所述的拆分操作的结果).

此外,您可以在setter中提供一些转换

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]);
    }
Run Code Online (Sandbox Code Playgroud)

为简单起见,我编写了转换方法,但请记住,除非您确定DateField始终包含有效日期且分数始终包含数字值,否则这也不是一种非常安全的方法.您可以尝试其他更安全的方法,如tryParse或一些异常处理.

我很诚实,它必须补充说上述解决方案很简单(根据要求),在概念层面上我会建议反对它.将属性和csv文件之间的映射逻辑放在类中会使体育类过于依赖文件本身,从而减少可重用性.然后,文件结构中的任何后续更改都应反映在您的课程中,并且通常会被忽略.因此,将"映射和转换"逻辑放在主程序中并尽可能保持您的类清洁会更明智

(通过将其格式化为2个字符串并结合连字符来更改"分数"问题)


Rob*_*ert 6

将sting拆分为数组以获取数据可能容易出错且速度慢.尝试使用OLE数据提供程序读取CSV,就好像它是SQL数据库中的表一样,这样您就可以使用WHERE子句来过滤结果.

<?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>
Run Code Online (Sandbox Code Playgroud)

编辑

我忘了展示csv应该如何看:)

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

            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);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 5

Linq 也有一个解决方案,您可以将输出定义为列表或数组。在下面的示例中,有一个类作为数据和数据类型的定义。

var modelData = File.ReadAllLines(dataFile)
                   .Skip(1)
                   .Select(x => x.Split(','))
                   .Select(dataRow => new TestModel
                   {
                       Column1 = dataRow[0],
                       Column2 = dataRow[1],
                       Column3 = dataRow[2],
                       Column4 = dataRow[3]
                   }).ToList(); // Or you can use .ToArray()
Run Code Online (Sandbox Code Playgroud)