【发布时间】:2010-11-27 03:55:02
【问题描述】:
如何使用 C# 读取 CSV 文件?
【问题讨论】:
如何使用 C# 读取 CSV 文件?
【问题讨论】:
不使用第三方组件的一种选择是使用类 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 */
}
【讨论】:
您可以在 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;
}
【讨论】:
你可以试试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 );
【讨论】:
我通常使用这样一种简单的方法:
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 规范转义的字段呢?等等。
我刚刚在我的应用程序中使用了这个库。 http://www.codeproject.com/KB/database/CsvReader.aspx。使用这个库一切都很顺利,所以我推荐它。它在 MIT 许可证下是免费的,因此只需在源文件中包含通知即可。
我没有在浏览器中显示 CSV,但作者有一些中继器或数据网格的示例。我确实运行了他的一个测试项目来测试我添加的排序操作,它看起来很不错。
【讨论】:
我推荐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");
【讨论】:
您可能对CodeProject 上的 Linq2Csv 库感兴趣。您需要检查的一件事是,如果它仅在需要时读取数据,那么在处理更大的文件时您将不需要大量内存。
至于在浏览器上显示数据,您可以做很多事情来完成它,如果您对您的要求更具体,答案可能更具体,但您可以做的事情:
1. 使用 HttpListener 类编写简单的 web 服务器(网上可以找到很多示例来托管 mini-http 服务器)。
2. 使用 Asp.Net 或 Asp.Net Mvc,创建一个页面,使用 IIS 托管它。
【讨论】:
似乎在 CodeProject 或 CodePlex 上有不少项目用于 CSV 解析。 这是 CodePlex 上的另一个 CSV 解析器
http://commonlibrarynet.codeplex.com/
这个库包含用于 CSV 解析、INI 文件解析、命令行解析的组件。到目前为止,它对我来说效果很好。唯一的问题是它没有 CSV Writer。
【讨论】:
这仅用于解析 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;
}
}
【讨论】:
多年来,我一直在维护一个名为 FlatFiles 的开源项目。它适用于 .NET Core 和 .NET 4.5.1。
与大多数替代方案不同,它允许您以极高的精度定义架构(类似于 EF 代码优先的工作方式),因此您不必一直与转换问题作斗争。您可以直接映射到您的数据类,并且还支持与旧 ADO.NET 类的接口。
在性能方面,它已被调整为最快的 .NET 解析器之一,具有大量用于古怪格式差异的选项。如果需要,还支持固定长度文件。
【讨论】:
您可以尝试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的文章了解如何使用它。
免责声明:我是这个库的作者
【讨论】:
你可以使用这个库: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<T>类的类型化对象。
【讨论】: