在DataGridView中读取CSV文件

时间:2016-01-05 12:43:21

标签: c# csv datagridview

我想将一个csv文件读入Datagridview。我想有一个类和一个函数来读取像这样的csv:

class Import
{
    public DataTable readCSV(string filePath)
    {            
        DataTable dt = new DataTable();
        using (StreamReader sr = new StreamReader(filePath))
        {
            string strLine = sr.ReadLine();     

            string[] strArray = strLine.Split(';');

            foreach (string value in strArray)
            {
                dt.Columns.Add(value.Trim());
            } 
            DataRow dr = dt.NewRow();

            while (sr.Peek() >= 0)
            {
                strLine = sr.ReadLine();
                strArray = strLine.Split(';');
                dt.Rows.Add(strArray);
            }
        }
        return dt;
     }   
}

并称之为:

Import imp = new Import();

DataTable table = imp.readCSV(filePath);
foreach(DataRow row in table.Rows)
{
 dataGridView.Rows.Add(row);
}

结果是 - >行已创建,但单元格中没有数据 !!

3 个答案:

答案 0 :(得分:6)

使用litle位linq

的第一种解决方案
public DataTable readCSV(string filePath)
{
    var dt = new DataTable();
    // Creating the columns
    File.ReadLines(filePath).Take(1)
        .SelectMany(x => x.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
        .ToList()
        .ForEach(x => dt.Columns.Add(x.Trim()));

    // Adding the rows
    File.ReadLines(filePath).Skip(1)
        .Select(x => x.Split(';'))
        .ToList()
        .ForEach(line => dt.Rows.Add(line));
    return dt;
}

使用foreach循环的另一个版本

public DataTable readCSV(string filePath)
{
    var dt = new DataTable();
    // Creating the columns
    foreach(var headerLine in File.ReadLines(filePath).Take(1))
    {
        foreach(var headerItem in headerLine.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
        {
            dt.Columns.Add(headerItem.Trim());
        }
    }

    // Adding the rows
    foreach(var line in File.ReadLines(filePath).Skip(1))
    {
        dt.Rows.Add(x.Split(';'));
    }
    return dt;
}

首先我们使用File.ReadLines,它返回一个行集合的IEnumerable。我们使用Take(1)来获得第一行,它应该是标题,然后我们使用SelectMany将在单个列表中转换从Split方法返回的字符串数组,因此我们调用ToList,现在我们可以使用ForEach方法在DataTable中添加列。

要添加行,我们仍然使用File.ReadLines,但现在我们跳过(1),跳过标题行,现在我们将使用Select,创建Collection<Collection<string>>,然后再次调用ToList ,最后调用ForEach在DataTable中添加行。 File.ReadLines在.NET 4.0中可用。

Obs。: File.ReadLines没有读取所有行,它返回一个IEnumerable,并且行是延迟评估的,所以只有第一行会加载两次。

See the MSDN remarks

  

ReadLines和ReadAllLines方法的不同之处如下:使用ReadLines时,可以在返回整个集合之前开始枚举字符串集合;当您使用ReadAllLines时,必须等待返回整个字符串数组才能访问该数组。因此,当您使用非常大的文件时,ReadLines可以更高效。

     

您可以使用ReadLines方法执行以下操作:

     

对文件执行LINQ to Objects查询以获取其过滤的一组行。

     

使用File.WriteAllLines(String,IEnumerable)方法将返回的行集合写入文件,或使用File.AppendAllLines(String,IEnumerable)方法将它们附加到现有文件。

     

创建一个立即填充的集合实例,该集合为其构造函数(例如IList或Queue)获取IEnumerable字符串集合。

     

此方法使用UTF8作为编码值。

如果您仍有任何疑问,请查看以下答案:What is the difference between File.ReadLines() and File.ReadAllLines()?

使用CsvHelper软件包的第二个解决方案

首先,安装此nuget包

PM> Install-Package CsvHelper 

对于给定的CSV,我们应该创建一个表示它的类

CSV文件

Name;Age;Birthdate;Working
Alberto Monteiro;25;01/01/1990;true
Other Person;5;01/01/2010;false

班级模型是

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    public DateTime Birthdate { get; set; }
    public bool Working { get; set; }
}

现在让我们使用CsvReader构建DataTable

public DataTable readCSV(string filePath)
{
    var dt = new DataTable();

    var csv = new CsvReader(new StreamReader(filePath));
    // Creating the columns
    typeof(Person).GetProperties().Select(p => p.Name).ToList().ForEach(x => dt.Columns.Add(x));

    // Adding the rows
    csv.GetRecords<Person>().ToList.ForEach(line => dt.Rows.Add(line.Name, line.Age, line.Birthdate, line.Working));
    return dt;
}

要在DataTable中创建列,请使用一些反射,然后使用方法GetRecords在DataTabble中添加行

答案 1 :(得分:4)

using Microsoft.VisualBasic.FileIO;

我建议如下。至少它应该具有优势&#39 ;;&#39;在一个字段中将被正确处理,并且它不受限于特定的csv格式。

public class CsvImport
{
    public static DataTable NewDataTable(string fileName, string delimiters, bool firstRowContainsFieldNames = true)
    {
        DataTable result = new DataTable();

        using (TextFieldParser tfp = new TextFieldParser(fileName))
        {
            tfp.SetDelimiters(delimiters); 

            // Get Some Column Names
            if (!tfp.EndOfData)
            {
                string[] fields = tfp.ReadFields();

                for (int i = 0; i < fields.Count(); i++)
                {
                    if (firstRowContainsFieldNames)
                        result.Columns.Add(fields[i]);
                    else 
                        result.Columns.Add("Col" + i);
                }

                // If first line is data then add it
                if (!firstRowContainsFieldNames)
                    result.Rows.Add(fields); 
            }

            // Get Remaining Rows
            while (!tfp.EndOfData) 
                result.Rows.Add(tfp.ReadFields());
        }

        return result;
    } 
}

答案 2 :(得分:0)

库中的

CsvHelper的Author构建功能。 代码变得简单了:

using (var reader = new StreamReader("path\\to\\file.csv"))
using (var csv = new CsvReader(reader, CultureInfo.CurrentCulture))
{
    // Do any configuration to `CsvReader` before creating CsvDataReader.
    using (var dr = new CsvDataReader(csv))
    {        
        var dt = new DataTable();
        dt.Load(dr);
    }
}

CultureInfo.CurrentCulture用于确定默认的分隔符,如果要读取Excel保存的csv,则需要此分隔符。