在 C# 中解析带有标题的 CSV 文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2081418/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 23:21:03  来源:igfitidea点击:

Parsing CSV files in C#, with header

c#csvfile-ioioheader

提问by David Pfeffer

Is there a default/official/recommended way to parse CSV files in C#? I don't want to roll my own parser.

是否有默认/官方/推荐的方法来解析 C# 中的 CSV 文件?我不想推出自己的解析器。

Also, I've seen instances of people using ODBC/OLE DB to read CSV via the Text driver, and a lot of people discourage this due to its "drawbacks." What are these drawbacks?

此外,我已经看到人们使用 ODBC/OLE DB 通过文本驱动程序读取 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.

理想情况下,我正在寻找一种可以通过列名读取 CSV 的方法,使用第一条记录作为标题/字段名称。给出的一些答案是正确的,但基本上可以将文件反序列化为类。

采纳答案by marc_s

Let a library handle all the nitty-gritty details for you! :-)

让图书馆为您处理所有细节!:-)

Check out FileHelpersand stay DRY - Don't Repeat Yourself - no need to re-invent the wheel a gazillionth time....

查看FileHelpers并保持干燥 - 不要重复自己 - 无需重新发明轮子无数次......

You basically just need to define that shape of your data - the fields in your individual line in the CSV - by means of a public class (and so well-thought out attributes like default values, replacements for NULL values and so forth), point the FileHelpers engine at a file, and bingo - you get back all the entries from that file. One simple operation - great performance!

您基本上只需要通过公共类(以及经过深思熟虑的属性,如默认值、NULL 值的替换等)来定义数据的形状 - CSV 中单独行中的字段文件中的 FileHelpers 引擎和宾果游戏 - 您可以从该文件中取回所有条目。一个简单的操作 - 出色的性能!

回答by Giorgi

If you need only reading csv files then I recommend this library: A Fast CSV Reader
If you also need to generate csv files then use this one: FileHelpers

如果您只需要读取 csv 文件,那么我推荐这个库:A Fast CSV Reader
如果您还需要生成 csv 文件,那么使用这个:FileHelpers

Both of them are free and opensource.

它们都是免费和开源的。

回答by alexn

In a business application, i use the Open Source project on codeproject.com, CSVReader.

在业务应用程序中,我使用 codeproject.com 上的开源项目CSVReader

It works well, and has good performance. There is some benchmarking on the link i provided.

它运行良好,并具有良好的性能。我提供的链接上有一些基准测试。

A simple example, copied from the project page:

一个简单的例子,复制自项目页面:

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();
    }
}

As you can see, it's very easy to work with.

如您所见,它很容易使用。

回答by Josh Close

CsvHelper(a library I maintain) will read a CSV file into custom objects.

CsvHelper(我维护的一个库)会将 CSV 文件读入自定义对象。

var csv = new CsvReader( File.OpenText( "file.csv" ) );
var myCustomObjects = csv.GetRecords<MyCustomObject>();

Sometimes you don't own the objects you're trying to read into. In this case, you can use fluent mapping because you can't put attributes on the class.

有时,您并不拥有要读取的对象。在这种情况下,您可以使用 fluent 映射,因为您不能在类上放置属性。

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>();
    }
}


EDIT:

编辑:

CsvReader now requires CultureInfo to be passed into the constuctor (https://github.com/JoshClose/CsvHelper/issues/1441).

CsvReader 现在需要将 CultureInfo 传递给构造函数 ( https://github.com/JoshClose/CsvHelper/issues/1441)。

Example:

例子:

var csv = new CsvReader(File.OpenText("file.csv"), System.Globalization.CultureInfo.CurrentCulture);

回答by Base33

Here is a helper class I use often, in case any one ever comes back to this thread (I wanted to share it).

这是我经常使用的一个助手类,以防万一有人回到这个线程(我想分享它)。

I use this for the simplicity of porting it into projects ready to use:

我使用它是为了简单地将它移植到准备使用的项目中:

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);
    }
  }
}

And use it like:

并像这样使用它:

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;
}

[Updated csv helper: bug fixed where the last new line character created a new line]

[更新的 csv 助手:修复了最后一个新行字符创建新行的错误]

回答by user1131926

I know its a bit late but just found a library Microsoft.VisualBasic.FileIOwhich has TextFieldParserclass to process csv files.

我知道它有点晚了,但刚刚找到了一个Microsoft.VisualBasic.FileIO具有TextFieldParser处理 csv 文件类的库。

回答by Alex

A CSV parser is now a part of .NET Framework.

CSV 解析器现在是 .NET Framework 的一部分。

Add a reference to Microsoft.VisualBasic.dll (works fine in C#, don't mind the name)

添加对 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
        }
    }
}

The docs are here - TextFieldParser Class

文档在这里 - TextFieldParser 类

P.S. If you need a CSV exporter, try CsvExport(discl: I'm one of the contributors)

PS 如果您需要 CSV导出器,请尝试CsvExport(光盘:我是贡献者之一)

回答by bytefish

I have written TinyCsvParserfor .NET, which is one of the fastest .NET parsers around and highly configurable to parse almost any CSV format.

我为 .NET编写了TinyCsvParser,它是最快的 .NET 解析器之一,并且高度可配置,几乎可以解析任何 CSV 格式。

It is released under MIT License:

它是在 MIT 许可证下发布的:

You can use NuGetto install it. Run the following command in the Package Manager Console.

您可以使用NuGet来安装它。在包管理器控制台中运行以下命令。

PM> Install-Package TinyCsvParser

Usage

用法

Imagine we have list of Persons in a CSV file persons.csvwith their first name, last name and birthdate.

想象一下,我们有一个 CSV 文件中的人员列表,persons.csv包括他们的名字、姓氏和生日。

FirstName;LastName;BirthDate
Philipp;Wagner;1986/05/12
Max;Musterman;2014/01/02

The corresponding domain model in our system might look like this.

我们系统中相应的领域模型可能如下所示。

private class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime BirthDate { get; set; }
}

When using TinyCsvParser you have to define the mapping between the columns in the CSV data and the property in you domain model.

使用 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);
    }
}

And then we can use the mapping to parse the CSV data with a CsvParser.

然后我们可以使用映射来解析带有 .csv 文件的 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);
        }
    }
}

User Guide

用户指南

A full User Guide is available at:

完整的用户指南可从以下网址获得:

回答by radsdau

Based on unlimit's post on How to properly split a CSV using C# split() function?:

基于 unlimit 关于如何使用 C# split() 函数正确拆分 CSV的帖子

string[] tokens = System.Text.RegularExpressions.Regex.Split(paramString, ",");

NOTE: this doesn't handle escaped / nested commas, etc., and therefore is only suitable for certain simple CSV lists.

注意:这不处理转义/嵌套逗号等,因此仅适用于某些简单的 CSV 列表。

回答by Jonas_Hess

This solution is using the official Microsoft.VisualBasicassembly to parse CSV.

此解决方案使用官方Microsoft.VisualBasic程序集来解析 CSV。

Advantages:

好处:

  • delimiter escaping
  • ignores Header
  • trim spaces
  • ignore comments
  • 分隔符转义
  • 忽略标题
  • 修剪空间
  • 忽略评论

Code:

代码:

    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;
    }