Dav*_*fer 248 c# csv io file-io header
是否有默认/官方/推荐的方法来解析C#中的CSV文件?我不想滚动自己的解析器.
此外,我已经看到人们使用ODBC/OLE DB通过Text驱动程序读取CSV的实例,很多人由于其"缺点"而不鼓励这种情况.这些缺点是什么?
Ideally, I'm looking for a way through which I can read the CSV by column name, using the first record as the header/field names. Some of the answers given are correct but work to basically deserialize the file into classes.
Ale*_*lex 335
CSV解析器现在是.NET Framework的一部分.
添加对Microsoft.VisualBasic.dll的引用(在C#中工作正常,不要介意名称)
using (TextFieldParser parser = new TextFieldParser(@"c:\temp\test.csv"))
{
parser.TextFieldType = FieldType.Delimited;
parser.SetDelimiters(",");
while (!parser.EndOfData)
{
//Process row
string[] fields = parser.ReadFields();
foreach (string field in fields)
{
//TODO: Process field
}
}
}
Run Code Online (Sandbox Code Playgroud)
文档在这里 - TextFieldParser类
Jos*_*ose 175
CsvHelper(我维护的库)会将CSV文件读入自定义对象.
var csv = new CsvReader( File.OpenText( "file.csv" ) );
var myCustomObjects = csv.GetRecords<MyCustomObject>();
Run Code Online (Sandbox Code Playgroud)
有时你不拥有你想要阅读的对象.在这种情况下,您可以使用流畅映射,因为您无法在类上放置属性.
public sealed class MyCustomObjectMap : CsvClassMap<MyCustomObject>
{
public MyCustomObjectMap()
{
Map( m => m.Property1 ).Name( "Column Name" );
Map( m => m.Property2 ).Index( 4 );
Map( m => m.Property3 ).Ignore();
Map( m => m.Property4 ).TypeConverter<MySpecialTypeConverter>();
}
}
Run Code Online (Sandbox Code Playgroud)
mar*_*c_s 132
Let a library handle all the nitty-gritty details for you! :-)
Check out FileHelpers and stay DRY - Don't Repeat Yourself - no need to re-invent the wheel a gazillionth time....
您基本上只需要通过公共类(以及经过深思熟虑的属性,如默认值,NULL值的替换等等)来定义数据的形状 - CSV中各行中的字段(点) FileHelpers引擎在一个文件和宾果游戏 - 你从该文件中获取所有条目.一个简单的操作 - 性能卓越!
ale*_*exn 31
在业务应用程序中,我使用codeproject.com上的开源项目CSVReader.
它运作良好,并具有良好的性能.我提供的链接有一些基准测试.
从项目页面复制的一个简单示例:
using (CsvReader csv = new CsvReader(new StreamReader("data.csv"), true))
{
int fieldCount = csv.FieldCount;
string[] headers = csv.GetFieldHeaders();
while (csv.ReadNextRecord())
{
for (int i = 0; i < fieldCount; i++)
Console.Write(string.Format("{0} = {1};", headers[i], csv[i]));
Console.WriteLine();
}
}
Run Code Online (Sandbox Code Playgroud)
如您所见,它非常容易使用.
Bas*_*e33 11
这是我经常使用的辅助类,以防任何人回到这个线程(我想分享它).
我使用它来简化将其移植到可以使用的项目中:
public class CSVHelper : List<string[]>
{
protected string csv = string.Empty;
protected string separator = ",";
public CSVHelper(string csv, string separator = "\",\"")
{
this.csv = csv;
this.separator = separator;
foreach (string line in Regex.Split(csv, System.Environment.NewLine).ToList().Where(s => !string.IsNullOrEmpty(s)))
{
string[] values = Regex.Split(line, separator);
for (int i = 0; i < values.Length; i++)
{
//Trim values
values[i] = values[i].Trim('\"');
}
this.Add(values);
}
}
}
Run Code Online (Sandbox Code Playgroud)
并使用它像:
public List<Person> GetPeople(string csvContent)
{
List<Person> people = new List<Person>();
CSVHelper csv = new CSVHelper(csvContent);
foreach(string[] line in csv)
{
Person person = new Person();
person.Name = line[0];
person.TelephoneNo = line[1];
people.Add(person);
}
return people;
}
Run Code Online (Sandbox Code Playgroud)
[更新了csv帮助程序:修复了最后一个新行字符创建新行的位置]
此解决方案使用官方Microsoft.VisualBasic程序集来解析CSV.
好处:
码:
using Microsoft.VisualBasic.FileIO;
public static List<List<string>> ParseCSV (string csv)
{
List<List<string>> result = new List<List<string>>();
// To use the TextFieldParser a reference to the Microsoft.VisualBasic assembly has to be added to the project.
using (TextFieldParser parser = new TextFieldParser(new StringReader(csv)))
{
parser.CommentTokens = new string[] { "#" };
parser.SetDelimiters(new string[] { ";" });
parser.HasFieldsEnclosedInQuotes = true;
// Skip over header line.
//parser.ReadLine();
while (!parser.EndOfData)
{
var values = new List<string>();
var readFields = parser.ReadFields();
if (readFields != null)
values.AddRange(readFields);
result.Add(values);
}
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
我编写了TinyCsvParser for .NET,它是最快的.NET解析器之一,可高度配置以解析几乎任何CSV格式.
它是在麻省理工学院许可下发布的:
您可以使用NuGet进行安装.在程序包管理器控制台中运行以下命令.
PM> Install-Package TinyCsvParser
Run Code Online (Sandbox Code Playgroud)
想象一下,我们在CSV文件中列出了人员名单,persons.csv
包括他们的名字,姓氏和生日.
FirstName;LastName;BirthDate
Philipp;Wagner;1986/05/12
Max;Musterman;2014/01/02
Run Code Online (Sandbox Code Playgroud)
我们系统中相应的域模型可能如下所示.
private class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime BirthDate { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
使用TinyCsvParser时,您必须定义CSV数据中的列与域模型中的属性之间的映射.
private class CsvPersonMapping : CsvMapping<Person>
{
public CsvPersonMapping()
: base()
{
MapProperty(0, x => x.FirstName);
MapProperty(1, x => x.LastName);
MapProperty(2, x => x.BirthDate);
}
}
Run Code Online (Sandbox Code Playgroud)
然后我们可以使用映射来解析CSV数据CsvParser
.
namespace TinyCsvParser.Test
{
[TestFixture]
public class TinyCsvParserTest
{
[Test]
public void TinyCsvTest()
{
CsvParserOptions csvParserOptions = new CsvParserOptions(true, new[] { ';' });
CsvPersonMapping csvMapper = new CsvPersonMapping();
CsvParser<Person> csvParser = new CsvParser<Person>(csvParserOptions, csvMapper);
var result = csvParser
.ReadFromFile(@"persons.csv", Encoding.ASCII)
.ToList();
Assert.AreEqual(2, result.Count);
Assert.IsTrue(result.All(x => x.IsValid));
Assert.AreEqual("Philipp", result[0].Result.FirstName);
Assert.AreEqual("Wagner", result[0].Result.LastName);
Assert.AreEqual(1986, result[0].Result.BirthDate.Year);
Assert.AreEqual(5, result[0].Result.BirthDate.Month);
Assert.AreEqual(12, result[0].Result.BirthDate.Day);
Assert.AreEqual("Max", result[1].Result.FirstName);
Assert.AreEqual("Mustermann", result[1].Result.LastName);
Assert.AreEqual(2014, result[1].Result.BirthDate.Year);
Assert.AreEqual(1, result[1].Result.BirthDate.Month);
Assert.AreEqual(1, result[1].Result.BirthDate.Day);
}
}
}
Run Code Online (Sandbox Code Playgroud)
完整的用户指南可在以下位置获得:
这是一个简短的解决方案。
using (TextFieldParser parser = new TextFieldParser(outputLocation))
{
parser.TextFieldType = FieldType.Delimited;
parser.SetDelimiters(",");
string[] headers = parser.ReadLine().Split(',');
foreach (string header in headers)
{
dataTable.Columns.Add(header);
}
while (!parser.EndOfData)
{
string[] fields = parser.ReadFields();
dataTable.Rows.Add(fields);
}
}
Run Code Online (Sandbox Code Playgroud)