使用 C# 读取 CSV 文件

发布于 2024-09-14 10:38:13 字数 617 浏览 3 评论 0原文

我正在编写一个简单的导入应用程序,需要读取 CSV 文件,在 DataGrid 中显示结果,并在另一个网格中显示 CSV 文件的损坏行。例如,显示另一个网格中短于 5 个值的线。我试图这样做:

StreamReader sr = new StreamReader(FilePath);
importingData = new Account();
string line;
string[] row = new string [5];
while ((line = sr.ReadLine()) != null)
{
    row = line.Split(',');

    importingData.Add(new Transaction
    {
        Date = DateTime.Parse(row[0]),
        Reference = row[1],
        Description = row[2],
        Amount = decimal.Parse(row[3]),
        Category = (Category)Enum.Parse(typeof(Category), row[4])
    });
}

但在这种情况下对数组进行操作非常困难。有没有更好的方法来分割值?

I'm writing a simple import application and need to read a CSV file, show result in a DataGrid and show corrupted lines of the CSV file in another grid. For example, show the lines that are shorter than 5 values in another grid. I'm trying to do that like this:

StreamReader sr = new StreamReader(FilePath);
importingData = new Account();
string line;
string[] row = new string [5];
while ((line = sr.ReadLine()) != null)
{
    row = line.Split(',');

    importingData.Add(new Transaction
    {
        Date = DateTime.Parse(row[0]),
        Reference = row[1],
        Description = row[2],
        Amount = decimal.Parse(row[3]),
        Category = (Category)Enum.Parse(typeof(Category), row[4])
    });
}

but it's very difficult to operate on arrays in this case. Is there a better way to split the values?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

梦幻之岛 2024-09-21 10:38:13

不要重新发明轮子。利用 .NET BCL 中已有的功能。

  • 添加对 Microsoft.VisualBasic 的引用(是的,它说的是 VisualBasic,但它在 C# 中也同样有效 - 请记住,最后它只是 IL)
  • 使用 Microsoft.VisualBasic。用于解析 CSV 文件的 FileIO.TextFieldParser 类

以下是示例代码:

using (TextFieldParser parser = new TextFieldParser(@"c:\temp\test.csv"))
{
    parser.TextFieldType = FieldType.Delimited;
    parser.SetDelimiters(",");
    while (!parser.EndOfData) 
    {
        //Processing row
        string[] fields = parser.ReadFields();
        foreach (string field in fields) 
        {
            //TODO: Process field
        }
    }
}

它在我的 C# 项目中非常适合我。

以下是更多链接/信息:

Don't reinvent the wheel. Take advantage of what's already in .NET BCL.

  • add a reference to the Microsoft.VisualBasic (yes, it says VisualBasic but it works in C# just as well - remember that at the end it is all just IL)
  • use the Microsoft.VisualBasic.FileIO.TextFieldParser class to parse CSV file

Here is the sample code:

using (TextFieldParser parser = new TextFieldParser(@"c:\temp\test.csv"))
{
    parser.TextFieldType = FieldType.Delimited;
    parser.SetDelimiters(",");
    while (!parser.EndOfData) 
    {
        //Processing row
        string[] fields = parser.ReadFields();
        foreach (string field in fields) 
        {
            //TODO: Process field
        }
    }
}

It works great for me in my C# projects.

Here are some more links/informations:

万人眼中万个我 2024-09-21 10:38:13

我推荐 来自 NuGet 的 CsvHelper



PS:关于其他更多赞成的答案,我很抱歉,但添加对 Microsoft.VisualBasic 的引用是:

  • 丑陋的
  • 不是跨平台的,因为它在 .NETCore/.NET5 中不可用(并且 Mono 从未有过)对 Visual Basic 的支持非常好,因此可能有问题)。

I recommend CsvHelper from NuGet.



PS: Regarding other more upvoted answers, I'm sorry but adding a reference to Microsoft.VisualBasic is:

  • Ugly
  • Not cross-platform, because it's not available in .NETCore/.NET5 (and Mono never had very good support of Visual Basic, so it may be buggy).
盗心人 2024-09-21 10:38:13

我的经验是,有许多不同的 csv 格式。特别是它们如何处理字段内引号和分隔符的转义。

这些是我遇到的变体:

  • 引号被引用并加倍(excel)即 15" -> field1,"15""",field3
  • 引号不会更改,除非该字段因其他原因被引用。即 15" - > field1,15",fields3
  • 引号用 \ 转义。即 15" -> field1,"15\"",field3
  • 引号根本没有改变(这并不总是能够正确解析)
  • 分隔符被引用(excel)。即 a,b -> field1,"a,b",field3
  • 分隔符是用 \. 转义,即 field1,a\,b,field3

我已经尝试了许多现有的 csv 解析器,但没有一个可以处理我遇到的变体。从文档中找出解析器支持哪些转义变体。

在我的项目中,我现在使用 VB TextFieldParser 或自定义拆分器。

My experience is that there are many different csv formats. Specially how they handle escaping of quotes and delimiters within a field.

These are the variants I have ran into:

  • quotes are quoted and doubled (excel) i.e. 15" -> field1,"15""",field3
  • quotes are not changed unless the field is quoted for some other reason. i.e. 15" -> field1,15",fields3
  • quotes are escaped with \. i.e. 15" -> field1,"15\"",field3
  • quotes are not changed at all (this is not always possible to parse correctly)
  • delimiter is quoted (excel). i.e. a,b -> field1,"a,b",field3
  • delimiter is escaped with \. i.e. a,b -> field1,a\,b,field3

I have tried many of the existing csv parsers but there is not a single one that can handle the variants I have ran into. It is also difficult to find out from the documentation which escaping variants the parsers support.

In my projects I now use either the VB TextFieldParser or a custom splitter.

情深如许 2024-09-21 10:38:13

有时,当您不想重新发明轮子时,使用库很酷,但在这种情况下,与使用库相比,可以用更少的代码行完成相同的工作,并且更易于阅读。
这是一种不同的方法,我发现它非常容易使用。

  1. 在此示例中,我使用 StreamReader 读取文件
  2. Regex 以检测每行的分隔符。
  3. 用于收集从索引 0 到 n 的列的数组

using (StreamReader reader = new StreamReader(fileName))
    {
        string line; 

        while ((line = reader.ReadLine()) != null)
        {
            //Define pattern
            Regex CSVParser = new Regex(",(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))");

            //Separating columns to array
            string[] X = CSVParser.Split(line);

            /* Do something with X */
        }
    }

Sometimes using libraries are cool when you do not want to reinvent the wheel, but in this case one can do the same job with fewer lines of code and easier to read compared to using libraries.
Here is a different approach which I find very easy to use.

  1. In this example, I use StreamReader to read the file
  2. Regex to detect the delimiter from each line(s).
  3. An array to collect the columns from index 0 to n

using (StreamReader reader = new StreamReader(fileName))
    {
        string line; 

        while ((line = reader.ReadLine()) != null)
        {
            //Define pattern
            Regex CSVParser = new Regex(",(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))");

            //Separating columns to array
            string[] X = CSVParser.Split(line);

            /* Do something with X */
        }
    }
浪漫之都 2024-09-21 10:38:13

CSV 可能会很快变得复杂真正

使用健壮且经过充分测试的东西:
文件助手:
www.filehelpers.net

FileHelpers 是一个免费且易于使用的 .NET 库,用于从文件、字符串或流中的固定长度或分隔记录导入/导出数据。

CSV can get complicated real fast.

Use something robust and well-tested:
FileHelpers:
www.filehelpers.net

The FileHelpers are a free and easy to use .NET library to import/export data from fixed length or delimited records in files, strings or streams.

野稚 2024-09-21 10:38:13

读取和写入 CSV 文件的开源库

此列表中的另一个是 Cinchoo ETL - 一个用于 下面的示例CSV文件

Id, Name
1, Tom
2, Mark

可以快速使用库加载它们,如下所示,

using (var reader = new ChoCSVReader("test.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; }
}

则可以使用它来加载CSV文件,如下所示,

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

请在CodeProject 了解如何使用它。

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

Another one to this list, Cinchoo ETL - an open source library to read and write CSV files

For a sample CSV file below

Id, Name
1, Tom
2, Mark

Quickly you can load them using library as below

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

If you have POCO class matching the CSV file

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

You can use it to load the CSV file as below

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

Please check out articles at CodeProject on how to use it.

Disclaimer: I'm the author of this library

沩ん囻菔务 2024-09-21 10:38:13

我在这里使用它:

http://www.codeproject.com/KB/database/GenericParser .aspx

上次我在寻找类似的东西时,我发现它是对此的答案 问题

I use this here:

http://www.codeproject.com/KB/database/GenericParser.aspx

Last time I was looking for something like this I found it as an answer to this question.

御守 2024-09-21 10:38:13

这是我今天编写的一个解决方案,用于解决我需要在不依赖外部库的情况下解析 CSV 的情况。我还没有测试大文件的性能,因为它与我的特定用例无关,但我希望它在大多数情况下都能表现得相当好。

        static List<List<string>> ParseCsv(string csv) {
            var parsedCsv = new List<List<string>>();
            var row = new List<string>();
            string field = "";
            bool inQuotedField = false;

            for (int i = 0; i < csv.Length; i++) {
                char current = csv[i];
                char next = i == csv.Length - 1 ? ' ' : csv[i + 1];

                // if current character is not a quote or comma or carriage return or newline (or not a quote and currently in an a quoted field), just add the character to the current field text
                if ((current != '"' && current != ',' && current != '\r' && current != '\n') || (current != '"' && inQuotedField)) {
                    field += current;
                } else if (current == ' ' || current == '\t') {
                    continue; // ignore whitespace outside a quoted field
                } else if (current == '"') {
                    if (inQuotedField && next == '"') { // quote is escaping a quote within a quoted field
                        i++; // skip escaping quote
                        field += current;
                    } else if (inQuotedField) { // quote signifies the end of a quoted field
                        row.Add(field);
                        if (next == ',') {
                            i++; // skip the comma separator since we've already found the end of the field
                        }
                        field = "";
                        inQuotedField = false;
                    } else { // quote signifies the beginning of a quoted field
                        inQuotedField = true; 
                    }
                } else if (current == ',') { //
                    row.Add(field);
                    field = "";
                } else if (current == '\n') {
                    row.Add(field);
                    parsedCsv.Add(new List<string>(row));
                    field = "";
                    row.Clear();
                }
            }

            return parsedCsv;
        }

Here's a solution I coded up today for a situation where I needed to parse a CSV without relying on external libraries. I haven't tested performance for large files since it wasn't relevant to my particular use case but I'd expect it to perform reasonably well for most situations.

        static List<List<string>> ParseCsv(string csv) {
            var parsedCsv = new List<List<string>>();
            var row = new List<string>();
            string field = "";
            bool inQuotedField = false;

            for (int i = 0; i < csv.Length; i++) {
                char current = csv[i];
                char next = i == csv.Length - 1 ? ' ' : csv[i + 1];

                // if current character is not a quote or comma or carriage return or newline (or not a quote and currently in an a quoted field), just add the character to the current field text
                if ((current != '"' && current != ',' && current != '\r' && current != '\n') || (current != '"' && inQuotedField)) {
                    field += current;
                } else if (current == ' ' || current == '\t') {
                    continue; // ignore whitespace outside a quoted field
                } else if (current == '"') {
                    if (inQuotedField && next == '"') { // quote is escaping a quote within a quoted field
                        i++; // skip escaping quote
                        field += current;
                    } else if (inQuotedField) { // quote signifies the end of a quoted field
                        row.Add(field);
                        if (next == ',') {
                            i++; // skip the comma separator since we've already found the end of the field
                        }
                        field = "";
                        inQuotedField = false;
                    } else { // quote signifies the beginning of a quoted field
                        inQuotedField = true; 
                    }
                } else if (current == ',') { //
                    row.Add(field);
                    field = "";
                } else if (current == '\n') {
                    row.Add(field);
                    parsedCsv.Add(new List<string>(row));
                    field = "";
                    row.Clear();
                }
            }

            return parsedCsv;
        }

我家小可爱 2024-09-21 10:38:13
private static DataTable ConvertCSVtoDataTable(string strFilePath)
        {
            DataTable dt = new DataTable();
            using (StreamReader sr = new StreamReader(strFilePath))
            {
                string[] headers = sr.ReadLine().Split(',');
                foreach (string header in headers)
                {
                    dt.Columns.Add(header);
                }
                while (!sr.EndOfStream)
                {
                    string[] rows = sr.ReadLine().Split(',');
                    DataRow dr = dt.NewRow();
                    for (int i = 0; i < headers.Length; i++)
                    {
                        dr[i] = rows[i];
                    }
                    dt.Rows.Add(dr);
                }

            }

            return dt;
        }

        private static void WriteToDb(DataTable dt)
        {
            string connectionString =
                "Data Source=localhost;" +
                "Initial Catalog=Northwind;" +
                "Integrated Security=SSPI;";

            using (SqlConnection con = new SqlConnection(connectionString))
                {
                    using (SqlCommand cmd = new SqlCommand("spInsertTest", con))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;

                        cmd.Parameters.Add("@policyID", SqlDbType.Int).Value = 12;
                        cmd.Parameters.Add("@statecode", SqlDbType.VarChar).Value = "blagh2";
                        cmd.Parameters.Add("@county", SqlDbType.VarChar).Value = "blagh3";

                        con.Open();
                        cmd.ExecuteNonQuery();
                    }
                }

         }
private static DataTable ConvertCSVtoDataTable(string strFilePath)
        {
            DataTable dt = new DataTable();
            using (StreamReader sr = new StreamReader(strFilePath))
            {
                string[] headers = sr.ReadLine().Split(',');
                foreach (string header in headers)
                {
                    dt.Columns.Add(header);
                }
                while (!sr.EndOfStream)
                {
                    string[] rows = sr.ReadLine().Split(',');
                    DataRow dr = dt.NewRow();
                    for (int i = 0; i < headers.Length; i++)
                    {
                        dr[i] = rows[i];
                    }
                    dt.Rows.Add(dr);
                }

            }

            return dt;
        }

        private static void WriteToDb(DataTable dt)
        {
            string connectionString =
                "Data Source=localhost;" +
                "Initial Catalog=Northwind;" +
                "Integrated Security=SSPI;";

            using (SqlConnection con = new SqlConnection(connectionString))
                {
                    using (SqlCommand cmd = new SqlCommand("spInsertTest", con))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;

                        cmd.Parameters.Add("@policyID", SqlDbType.Int).Value = 12;
                        cmd.Parameters.Add("@statecode", SqlDbType.VarChar).Value = "blagh2";
                        cmd.Parameters.Add("@county", SqlDbType.VarChar).Value = "blagh3";

                        con.Open();
                        cmd.ExecuteNonQuery();
                    }
                }

         }
盛夏已如深秋| 2024-09-21 10:38:13

首先需要了解什么是CSV以及如何编写它。

  1. 每个下一个字符串( /r/n )是下一个“表”行。
  2. “表格”单元格由一些分隔符分隔。最常用的符号是 \t,
  3. 每个单元格都可能包含此分隔符(在这种情况下,单元格必须以引号符号开头,并以此符号结尾)
  4. 每个单元格可能可以包含 /r/n 符号(在这种情况下,单元格必须以引号符号开头,并以该符号结尾)

C#/Visual Basic 处理 CSV 文件的最简单方法是使用标准 <代码>Microsoft.VisualBasic 库。您只需将所需的引用和以下字符串添加到您的类中:

using Microsoft.VisualBasic.FileIO;

是的,您可以在 C# 中使用它,不用担心。该库可以读取相对较大的文件并支持所有所需的规则,因此您将能够使用所有 CSV 文件。

前段时间我基于这个库编写了用于 CSV 读/写的简单类。使用这个简单的类,您将能够像使用二维数组一样使用 CSV。
您可以通过以下链接找到我的课程:
https://github.com/ukushu/DataExporter

简单的使用示例:

Csv csv = new Csv("\t");//delimiter symbol

csv.FileOpen("c:\\file1.csv");

var row1Cell6Value = csv.Rows[0][5];

csv.AddRow("asdf","asdffffff","5")

csv.FileSave("c:\\file2.csv");

First of all need to understand what is CSV and how to write it.

  1. Every next string ( /r/n ) is next "table" row.
  2. "Table" cells is separated by some delimiter symbol. Most often used symbols is \t or ,
  3. Every cell possibly can contain this delimiter symbol (cell must to start with quotes symbol and ends with this symbol in this case)
  4. Every cell possibly can contains /r/n sybols (cell must to start with quotes symbol and ends with this symbol in this case)

The easiest way for C#/Visual Basic to work with CSV files is to use standard Microsoft.VisualBasic library. You just need to add needed reference, and the following string to your class:

using Microsoft.VisualBasic.FileIO;

Yes, you can use it in C#, don't worry. This library can read relatively big files and supports all of needed rules, so you will be able to work with all of CSV files.

Some time ago I had wrote simple class for CSV read/write based on this library. Using this simple class you will be able to work with CSV like with 2 dimensions array.
You can find my class by the following link:
https://github.com/ukushu/DataExporter

Simple example of using:

Csv csv = new Csv("\t");//delimiter symbol

csv.FileOpen("c:\\file1.csv");

var row1Cell6Value = csv.Rows[0][5];

csv.AddRow("asdf","asdffffff","5")

csv.FileSave("c:\\file2.csv");
神爱温柔 2024-09-21 10:38:13

要完成前面的答案,可能需要 CSV 文件中的对象集合,由 TextFieldParserstring.Split 方法解析,然后将每一行转换为通过反射的对象。显然,您首先需要定义一个与 CSV 文件的行匹配的类。

我使用了来自 Michael Kropat 的简单 CSV 序列化器:通用类到 CSV(所有属性)
并重用他的方法来获取所需类的字段和属性。

我使用以下方法反序列化我的 CSV 文件:

public static IEnumerable<T> ReadCsvFileTextFieldParser<T>(string fileFullPath, string delimiter = ";") where T : new()
{
    if (!File.Exists(fileFullPath))
    {
        return null;
    }

    var list = new List<T>();
    var csvFields = GetAllFieldOfClass<T>();
    var fieldDict = new Dictionary<int, MemberInfo>();

    using (TextFieldParser parser = new TextFieldParser(fileFullPath))
    {
        parser.SetDelimiters(delimiter);

        bool headerParsed = false;

        while (!parser.EndOfData)
        {
            //Processing row
            string[] rowFields = parser.ReadFields();
            if (!headerParsed)
            {
                for (int i = 0; i < rowFields.Length; i++)
                {
                    // First row shall be the header!
                    var csvField = csvFields.Where(f => f.Name == rowFields[i]).FirstOrDefault();
                    if (csvField != null)
                    {
                        fieldDict.Add(i, csvField);
                    }
                }
                headerParsed = true;
            }
            else
            {
                T newObj = new T();
                for (int i = 0; i < rowFields.Length; i++)
                {
                    var csvFied = fieldDict[i];
                    var record = rowFields[i];

                    if (csvFied is FieldInfo)
                    {
                        ((FieldInfo)csvFied).SetValue(newObj, record);
                    }
                    else if (csvFied is PropertyInfo)
                    {
                        var pi = (PropertyInfo)csvFied;
                        pi.SetValue(newObj, Convert.ChangeType(record, pi.PropertyType), null);
                    }
                    else
                    {
                        throw new Exception("Unhandled case.");
                    }
                }
                if (newObj != null)
                {
                    list.Add(newObj);
                }
            }
        }
    }
    return list;
}

public static IEnumerable<MemberInfo> GetAllFieldOfClass<T>()
{
    return
        from mi in typeof(T).GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)
        where new[] { MemberTypes.Field, MemberTypes.Property }.Contains(mi.MemberType)
        let orderAttr = (ColumnOrderAttribute)Attribute.GetCustomAttribute(mi, typeof(ColumnOrderAttribute))
        orderby orderAttr == null ? int.MaxValue : orderAttr.Order, mi.Name
        select mi;            
}

To complete the previous answers, one may need a collection of objects from his CSV File, either parsed by the TextFieldParser or the string.Split method, and then each line converted to an object via Reflection. You obviously first need to define a class that matches the lines of the CSV file.

I used the simple CSV Serializer from Michael Kropat found here: Generic class to CSV (all properties)
and reused his methods to get the fields and properties of the wished class.

I deserialize my CSV file with the following method:

public static IEnumerable<T> ReadCsvFileTextFieldParser<T>(string fileFullPath, string delimiter = ";") where T : new()
{
    if (!File.Exists(fileFullPath))
    {
        return null;
    }

    var list = new List<T>();
    var csvFields = GetAllFieldOfClass<T>();
    var fieldDict = new Dictionary<int, MemberInfo>();

    using (TextFieldParser parser = new TextFieldParser(fileFullPath))
    {
        parser.SetDelimiters(delimiter);

        bool headerParsed = false;

        while (!parser.EndOfData)
        {
            //Processing row
            string[] rowFields = parser.ReadFields();
            if (!headerParsed)
            {
                for (int i = 0; i < rowFields.Length; i++)
                {
                    // First row shall be the header!
                    var csvField = csvFields.Where(f => f.Name == rowFields[i]).FirstOrDefault();
                    if (csvField != null)
                    {
                        fieldDict.Add(i, csvField);
                    }
                }
                headerParsed = true;
            }
            else
            {
                T newObj = new T();
                for (int i = 0; i < rowFields.Length; i++)
                {
                    var csvFied = fieldDict[i];
                    var record = rowFields[i];

                    if (csvFied is FieldInfo)
                    {
                        ((FieldInfo)csvFied).SetValue(newObj, record);
                    }
                    else if (csvFied is PropertyInfo)
                    {
                        var pi = (PropertyInfo)csvFied;
                        pi.SetValue(newObj, Convert.ChangeType(record, pi.PropertyType), null);
                    }
                    else
                    {
                        throw new Exception("Unhandled case.");
                    }
                }
                if (newObj != null)
                {
                    list.Add(newObj);
                }
            }
        }
    }
    return list;
}

public static IEnumerable<MemberInfo> GetAllFieldOfClass<T>()
{
    return
        from mi in typeof(T).GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)
        where new[] { MemberTypes.Field, MemberTypes.Property }.Contains(mi.MemberType)
        let orderAttr = (ColumnOrderAttribute)Attribute.GetCustomAttribute(mi, typeof(ColumnOrderAttribute))
        orderby orderAttr == null ? int.MaxValue : orderAttr.Order, mi.Name
        select mi;            
}
尬尬 2024-09-21 10:38:13

我强烈建议使用 CsvHelper。

这是一个简单的示例:

public class csvExampleClass
{
    public string Id { get; set; }
    public string Firstname { get; set; }
    public string Lastname { get; set; }
}

var items = DeserializeCsvFile<List<csvExampleClass>>( csvText );

public static List<T> DeserializeCsvFile<T>(string text)
{
    CsvReader csv = new CsvReader( new StringReader( text ) );
    csv.Configuration.Delimiter = ",";
    csv.Configuration.HeaderValidated = null;
    csv.Configuration.MissingFieldFound = null;
    return (List<T>)csv.GetRecords<T>();
}

完整的文档可以在以下位置找到:https://joshclose.github.io/CsvHelper

I'd highly suggest using CsvHelper.

Here's a quick example:

public class csvExampleClass
{
    public string Id { get; set; }
    public string Firstname { get; set; }
    public string Lastname { get; set; }
}

var items = DeserializeCsvFile<List<csvExampleClass>>( csvText );

public static List<T> DeserializeCsvFile<T>(string text)
{
    CsvReader csv = new CsvReader( new StringReader( text ) );
    csv.Configuration.Delimiter = ",";
    csv.Configuration.HeaderValidated = null;
    csv.Configuration.MissingFieldFound = null;
    return (List<T>)csv.GetRecords<T>();
}

Full documentation can be found at: https://joshclose.github.io/CsvHelper

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文