在C#中读取CSV文件

有谁知道一个开源库,允许您parsing和读取C#中的.csv文件?

看看CodeProject上的快速CSV阅读器 。

在这里,你真的写了使用generics集合和迭代器块。 它支持使用双转义约定(所以""在引用字段内部读作单引号字符)的双引号括号文本字段(包括跨越多行的字段)。 它不支持:

  • 单引号封闭的文本
  • 引用了引用的文字
  • 备用分隔符(将不会在pipe道或制表符分隔的字段上工作)
  • 以引号开头的未加引号的文本字段

但是如果你需要的话,所有这些都很容易添加。 我没有在任何地方进行基准testing(我希望看到一些结果),但性能应该是非常好的 ,比任何基于.Split()的都好。

现在在GitHub上

更新 :觉得像添加单引号封闭的文字支持。 这是一个简单的改变,但是我把它直接input回复窗口,所以没有经过testing。 如果您更喜欢旧的(testing过的)代码,请使用底部的修订链接。

 public static class CSV { public static IEnumerable<IList<string>> FromFile(string fileName) { foreach (IList<string> item in FromFile(fileName, ignoreFirstLineDefault)) yield return item; } public static IEnumerable<IList<string>> FromFile(string fileName, bool ignoreFirstLine) { using (StreamReader rdr = new StreamReader(fileName)) { foreach(IList<string> item in FromReader(rdr, ignoreFirstLine)) yield return item; } } public static IEnumerable<IList<string>> FromStream(Stream csv) { foreach (IList<string> item in FromStream(csv, ignoreFirstLineDefault)) yield return item; } public static IEnumerable<IList<string>> FromStream(Stream csv, bool ignoreFirstLine) { using (var rdr = new StreamReader(csv)) { foreach (IList<string> item in FromReader(rdr, ignoreFirstLine)) yield return item; } } public static IEnumerable<IList<string>> FromReader(TextReader csv) { //Probably should have used TextReader instead of StreamReader foreach (IList<string> item in FromReader(csv, ignoreFirstLineDefault)) yield return item; } public static IEnumerable<IList<string>> FromReader(TextReader csv, bool ignoreFirstLine) { if (ignoreFirstLine) csv.ReadLine(); IList<string> result = new List<string>(); StringBuilder curValue = new StringBuilder(); char c; c = (char)csv.Read(); while (csv.Peek() != -1) { switch (c) { case ',': //empty field result.Add(""); c = (char)csv.Read(); break; case '"': //qualified text case '\'': char q = c; c = (char)csv.Read(); bool inQuotes = true; while (inQuotes && csv.Peek() != -1) { if (c == q) { c = (char)csv.Read(); if (c != q) inQuotes = false; } if (inQuotes) { curValue.Append(c); c = (char)csv.Read(); } } result.Add(curValue.ToString()); curValue = new StringBuilder(); if (c == ',') c = (char)csv.Read(); // either ',', newline, or endofstream break; case '\n': //end of the record case '\r': //potential bug here depending on what your line breaks look like if (result.Count > 0) // don't return empty records { yield return result; result = new List<string>(); } c = (char)csv.Read(); break; default: //normal unqualified text while (c != ',' && c != '\r' && c != '\n' && csv.Peek() != -1) { curValue.Append(c); c = (char)csv.Read(); } result.Add(curValue.ToString()); curValue = new StringBuilder(); if (c == ',') c = (char)csv.Read(); //either ',', newline, or endofstream break; } } if (curValue.Length > 0) //potential bug: I don't want to skip on a empty column in the last record if a caller really expects it to be there result.Add(curValue.ToString()); if (result.Count > 0) yield return result; } private static bool ignoreFirstLineDefault = false; } 

上次问这个问题 ,我给出的答案是 :

如果您只是想用C#读取CSV文件,最简单的方法就是使用Microsoft.VisualBasic.FileIO.TextFieldParser类。 它实际上内置于.NET Framework中,而不是第三方扩展。

是的,它在Microsoft.VisualBasic.dll ,但这并不意味着你不能从C#(或任何其他CLR语言)使用它。

下面是一个使用示例,摘自MSDN文档 :

 Using MyReader As New _ Microsoft.VisualBasic.FileIO.TextFieldParser("C:\testfile.txt") MyReader.TextFieldType = FileIO.FieldType.Delimited MyReader.SetDelimiters(",") Dim currentRow As String() While Not MyReader.EndOfData Try currentRow = MyReader.ReadFields() Dim currentField As String For Each currentField In currentRow MsgBox(currentField) Next Catch ex As Microsoft.VisualBasic.FileIO.MalformedLineException MsgBox("Line " & ex.Message & _ "is not valid and will be skipped.") End Try End While End Using 

再次,这个例子是在VB.NET中,但将它翻译成C#将是微不足道的。

我真的很喜欢FileHelpers库。 它很快,它是C#100%,它是免费的 ,它非常灵活和易于使用。

我正在用C#实现Daniel Pryden的答案,所以剪切,粘贴和自定义更容易。 我认为这是parsingCSV文件最简单的方法。 只需添加一个参考,你基本上完成。

Microsoft.VisualBasic引用添加到您的项目

那么这里是来自Joel的答案在C#中的示例代码:

 using (Microsoft.VisualBasic.FileIO.TextFieldParser MyReader = new Microsoft.VisualBasic.FileIO.TextFieldParser(filename)) { MyReader.TextFieldType = Microsoft.VisualBasic.FileIO.FieldType.Delimited; MyReader.SetDelimiters(","); while (!MyReader.EndOfData) { try { string[] fields = MyReader.ReadFields(); if (first) { first = false; continue; } // This is how I treat my data, you'll need to throw this out. //"Type" "Post Date" "Description" "Amount" LineItem li = new LineItem(); li.date = DateTime.Parse(fields[1]); li.description = fields[2]; li.Value = Convert.ToDecimal(fields[3]); lineitems1.Add(li); } catch (Microsoft.VisualBasic.FileIO.MalformedLineException ex) { MessageBox.Show("Line " + ex.Message + " is not valid and will be skipped."); } } } 

除了parsing/阅读之外,一些库还有其他很好的function,例如将parsing的数据转换为对象。

以下是使用CsvHelper将CSV文件读入对象的示例。

 var csv = new CsvHelper( File.OpenRead( "file.csv" ) ); var myCustomObjectList = csv.Reader.GetRecords<MyCustomObject>(); 

默认情况下,约定用于匹配标题/列与属性。 您可以通过更改设置来更改行为。

 // Using attributes: public class MyCustomObject { [CsvField( Name = "First Name" )] public string StringProperty { get; set; } [CsvField( Index = 0 )] public int IntProperty { get; set; } [CsvField( Ignore = true )] public string ShouldIgnore { get; set; } } 

有时你并不拥有你想要用来填充数据的对象。 在这种情况下,你可以使用stream利的类映射。

 // Fluent class mapping: public sealed class MyCustomObjectMap : CsvClassMap<MyCustomObject> { public MyCustomObjectMap() { Map( m => m.StringProperty ).Name( "First Name" ); Map( m => m.IntProperty ).Index( 0 ); Map( m => m.ShouldIgnore ).Ignore(); } } 

您可以使用Microsoft.VisualBasic.FileIO.TextFieldParser

从上面的文章得到下面的代码示例

 static void Main() { string csv_file_path=@"C:\Users\Administrator\Desktop\test.csv"; DataTable csvData = GetDataTabletFromCSVFile(csv_file_path); Console.WriteLine("Rows count:" + csvData.Rows.Count); Console.ReadLine(); } private static DataTable GetDataTabletFromCSVFile(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; }