【问题标题】:Reading a CSV file in .NET?在 .NET 中读取 CSV 文件?
【发布时间】:2010-11-27 03:55:02
【问题描述】:

如何使用 C# 读取 CSV 文件?

【问题讨论】:

标签: c# .net csv browser


【解决方案1】:

不使用第三方组件的一种选择是使用类 Microsoft.VisualBasic.FileIO.TextFieldParser (http://msdn.microsoft.com/en-us/library/microsoft.visualbasic.fileio.textfieldparser.aspx) 。它提供了解析 CSV 的所有功能。导入 Microsoft.VisualBasic 程序集就足够了。

var parser = new Microsoft.VisualBasic.FileIO.TextFieldParser(file);
parser.TextFieldType = Microsoft.VisualBasic.FileIO.FieldType.Delimited;
parser.SetDelimiters(new string[] { ";" });

while (!parser.EndOfData)
{
    string[] row = parser.ReadFields();
    /* do something */
}

【讨论】:

  • 对于读取 CSV 文件并自己提供解析,这是理想的选择。简单但功能齐全,包括多行引用的值。
  • 这是我最喜欢的开箱即用解决方案
【解决方案2】:

您可以在 C# 中使用 Microsoft.VisualBasic.FileIO.TextFieldParser 类:

using System;
using System.Data;
using Microsoft.VisualBasic.FileIO;

static void Main()
{
    string csv_file_path = @"C:\Users\Administrator\Desktop\test.csv";

    DataTable csvData = GetDataTableFromCSVFile(csv_file_path);

    Console.WriteLine("Rows count:" + csvData.Rows.Count);    
    Console.ReadLine();
}

private static DataTable GetDataTableFromCSVFile(string csv_file_path)
{
    DataTable csvData = new DataTable();

    try
    {
        using(TextFieldParser csvReader = new TextFieldParser(csv_file_path))
        {
            csvReader.SetDelimiters(new string[] { "," });
            csvReader.HasFieldsEnclosedInQuotes = true;
            string[] colFields = csvReader.ReadFields();

            foreach (string column in colFields)
            {
                DataColumn datecolumn = new DataColumn(column);
                datecolumn.AllowDBNull = true;
                csvData.Columns.Add(datecolumn);
            }

            while (!csvReader.EndOfData)
            {
                string[] fieldData = csvReader.ReadFields();
                //Making empty value as null
                for (int i = 0; i < fieldData.Length; i++)
                {
                    if (fieldData[i] == "")
                    {
                        fieldData[i] = null;
                    }
                }

                csvData.Rows.Add(fieldData);
             }
         }
     }
     catch (Exception ex)
     {
     }

     return csvData;
}

【讨论】:

  • 这个库是我最喜欢的开箱即用解决方案。
  • 我从这个例子中唯一改变的是检查相同的列名并添加了一些代码来显示异常
【解决方案3】:

你可以试试CsvHelper,这是我从事的一个项目。它的目标是让读取和写入 CSV 文件尽可能简单,同时速度非常快。

您可以通过以下几种方式读取 CSV 文件。

// By type
var records = csv.GetRecords<MyClass>();
var records = csv.GetRecords( typeof( MyClass ) );

// Dynamic
var records = csv.GetRecords<dynamic>();

// Using anonymous type for the class definition
var anonymousTypeDefinition =
{
    Id = default( int ),
    Name = string.Empty,
    MyClass = new MyClass()
};
var records = csv.GetRecords( anonymousTypeDefinition );

【讨论】:

    【解决方案4】:

    我通常使用这样一种简单的方法:

    var path = Server.MapPath("~/App_Data/Data.csv");
    var csvRows = System.IO.File.ReadAllLines(path, Encoding.Default).ToList();
    
    foreach (var row in csvRows.Skip(1))
    {
        var columns = row.Split(';');
    
        var field1 = columns[0];
        var field2 = columns[1];
        var field3 = columns[2];
    }
    

    【讨论】:

    • 简单总是最好的。
    • 这会将整个文件加载到内存中,这可能是个问题。另外,如果字段包含; 或换行符怎么办?根据 RFC 4180 规范转义的字段呢?等等。
    • 感谢您指出实现的缺陷。这些确实是这种方式的陷阱。但正如您所见,实现既快速又简单——因此它可能非常适合许多用例。它对我有用
    【解决方案5】:

    我刚刚在我的应用程序中使用了这个库。 http://www.codeproject.com/KB/database/CsvReader.aspx。使用这个库一切都很顺利,所以我推荐它。它在 MIT 许可证下是免费的,因此只需在源文件中包含通知即可。

    我没有在浏览器中显示 CSV,但作者有一些中继器或数据网格的示例。我确实运行了他的一个测试项目来测试我添加的排序操作,它看起来很不错。

    【讨论】:

      【解决方案6】:

      我推荐Angara.Table,关于保存/加载:http://predictionmachines.github.io/Angara.Table/saveload.html

      它可以进行列类型推断,可以保存 CSV 文件,并且比 TextFieldParser 快得多。它遵循 CSV 格式的 RFC4180,支持多行字符串、NaN 和包含分隔符的转义字符串。

      该库受 MIT 许可。源代码是https://github.com/Microsoft/Angara.Table

      虽然它的 API 专注于 F#,但它可以用于任何 .NET 语言,但不如 F# 简洁。

      例子:

      using Angara.Data;
      using System.Collections.Immutable;
      
      ...
      
      var table = Table.Load("data.csv");
      
      // Print schema:
      foreach(Column c in table)
      {
          string colType;
          if (c.Rows.IsRealColumn) colType = "double";
          else if (c.Rows.IsStringColumn) colType = "string";
          else if (c.Rows.IsDateColumn) colType = "date";
          else if (c.Rows.IsIntColumn) colType = "int";
          else colType = "bool";
      
          Console.WriteLine("{0} of type {1}", c.Name, colType);
      }
      
      // Get column data:
      ImmutableArray<double> a = table["a"].Rows.AsReal;
      ImmutableArray<string> b = table["b"].Rows.AsString;
      
      Table.Save(table, "data2.csv");
      

      【讨论】:

        【解决方案7】:

        您可能对CodeProject 上的 Linq2Csv 库感兴趣。您需要检查的一件事是,如果它仅在需要时读取数据,那么在处理更大的文件时您将不需要大量内存。

        至于在浏览器上显示数据,您可以做很多事情来完成它,如果您对您的要求更具体,答案可能更具体,但您可以做的事情:
        1. 使用 HttpListener 类编写简单的 web 服务器(网上可以找到很多示例来托管 mini-http 服务器)。
        2. 使用 Asp.Net 或 Asp.Net Mvc,创建一个页面,使用 IIS 托管它。

        【讨论】:

          【解决方案8】:

          似乎在 CodeProject 或 CodePlex 上有不少项目用于 CSV 解析。 这是 CodePlex 上的另一个 CSV 解析器

          http://commonlibrarynet.codeplex.com/

          这个库包含用于 CSV 解析、INI 文件解析、命令行解析的组件。到目前为止,它对我来说效果很好。唯一的问题是它没有 CSV Writer。

          【讨论】:

          • 仅供参考:网站上的许可证说它是 MIT,但在源代码本身中,所有 Csv 相关文件的顶部都有显眼的 LGPL 许可证。
          【解决方案9】:

          这仅用于解析 CSV。为了在网页中显示它,只需获取列表并根据需要呈现它。

          注意:此代码示例不处理输入字符串line 包含换行符的情况。

          public List<string> SplitCSV(string line)
          {
              if (string.IsNullOrEmpty(line))
                  throw new ArgumentException();
          
              List<string> result = new List<string>();
          
              int index = 0;
              int start = 0;
              bool inQuote = false;
              StringBuilder val = new StringBuilder();
          
              // parse line
              foreach (char c in line)
              {
                  switch (c)
                  {
                      case '"':
                          inQuote = !inQuote;
                          break;
          
                      case ',':
                          if (!inQuote)
                          {
                              result.Add(line.Substring(start, index - start)
                                  .Replace("\"",""));
          
                              start = index + 1;
                          }
          
                          break;
                      }
          
                      index++;
                  }
          
                  if (start < index)
                  {
                      result.Add(line.Substring(start, index - start).Replace("\"",""));
                  }
          
                  return result;
              }
          }
          

          【讨论】:

          • 它也不处理值中双引号字符的使用。 CSV 有很多边缘情况,最好只使用库。
          【解决方案10】:

          多年来,我一直在维护一个名为 FlatFiles 的开源项目。它适用于 .NET Core 和 .NET 4.5.1。

          与大多数替代方案不同,它允许您以极高的精度定义架构(类似于 EF 代码优先的工作方式),因此您不必一直与转换问题作斗争。您可以直接映射到您的数据类,并且还支持与旧 ADO.NET 类的接口。

          在性能方面,它已被调整为最快的 .NET 解析器之一,具有大量用于古怪格式差异的选项。如果需要,还支持固定长度文件。

          【讨论】:

          【解决方案11】:

          您可以尝试Cinchoo ETL - 一个用于读写 CSV 文件的开源库。

          读取 CSV 文件的几种方法

          Id, Name
          1, Tom
          2, Mark
          

          这就是你如何使用这个库来阅读它

          using (var reader = new ChoCSVReader("emp.csv").WithFirstLineHeader())
          {
             foreach (dynamic item in reader)
             {
                Console.WriteLine(item.Id);
                Console.WriteLine(item.Name);
             }
          }
          

          如果您定义了 POCO 对象以匹配 CSV 文件,如下所示

          public class Employee
          {
             public int Id { get; set; }
             public string Name { get; set; }
          }
          

          您可以使用下面的这个 POCO 类解析相同的文件

          using (var reader = new ChoCSVReader<Employee>("emp.csv").WithFirstLineHeader())
          {
             foreach (var item in reader)
             {
                Console.WriteLine(item.Id);
                Console.WriteLine(item.Name);
             }
          }
          

          请查看CodeProject的文章了解如何使用它。

          免责声明:我是这个库的作者

          【讨论】:

          • 我更喜欢这个库。谢谢
          【解决方案12】:

          你可以使用这个库:Sky.Data.Csv https://www.nuget.org/packages/Sky.Data.Csv/ 这是一个非常快速的 CSV 阅读器库,而且非常易于使用:

          using Sky.Data.Csv;
          
          var readerSettings = new CsvReaderSettings{Encoding = Encoding.UTF8};
          using(var reader = CsvReader.Create("path-to-file", readerSettings)){
              foreach(var row in reader){
                  //do something with the data
              }
          }
          

          它还支持读取具有相同接口的CsvReader&lt;T&gt;类的类型化对象。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2019-04-15
            • 2012-09-28
            • 2016-04-09
            • 2023-03-22
            • 2011-07-24
            • 2022-01-09
            • 2015-07-21
            相关资源
            最近更新 更多