什么是在c#中异步解析CSV文件的最佳方式

时间:2014-12-28 23:56:19

标签: c# csv asynchronous

我必须解析大的CSV文件并提高吞吐量我使用异步和等待。我当前的方法是逐行读取文件并执行我自己的解析:

using (var streamReader = File.OpenText(fileName))
{
  string line;
  while ((line = await streamReader.ReadLineAsync()) != null)
  {
    // Parse line ...
  }
}

然而,正确解析CSV文件并不容易,例如当字符串包含逗号等时。

我一直无法找到兼容性和支持异步和等待的CSV解析器。如何在不编写解析器的情况下使用异步I / O有效地解析CSV文件?

2 个答案:

答案 0 :(得分:2)

您可以查看非常有用且易于使用的CsvHelper library(也可用作NuGet package)。这甚至包括内置的mapping功能,可将CSV记录映射到对象。

  

CSV Helper用于读取和写入CSV文件的.NET库。极其快速,灵活且易于使用。支持阅读和写作   自定义类对象。

它不是异步的(如在async/await中),但是如评论中所建议的那样,您可以围绕它创建自己的异步包装。

答案 1 :(得分:1)

我是CsvHelper的推荐。这是我用来异步加载CSV文件集合的类。它确实等待数据在返回之前被读取:

public CsvParser()
{
    Task[] LoadData = new Task[3]
    {
        Task.Factory.StartNew(
            () => 
                {
                    IEnumerable<MachineDetail> Machines = GetCsvContents<MachineDetail>("MachineDetail*.csv");
                    this.MachineData.AddRange(Machines);
                }
            ),

        Task.Factory.StartNew(
            () => 
                {
                    IEnumerable<SiteDetail> Sites = GetCsvContents<SiteDetail>("SiteDetail*.csv");
                    this.SiteData.AddRange(Sites);
                }
            ),

        Task.Factory.StartNew(
            () => 
                {
                    IEnumerable<KeyDetail> Keys = GetCsvContents<KeyDetail>("_keysheets_*.csv");
                    this.KeyData.AddRange(Keys);
                }
            )
    };

    Task.WaitAll(LoadData);
}

private List<T> GetCsvContents<T>(string CsvFileName)
{
    List<T> ReturnContents = new List<T>();

    FileInfo[] CsvFiles = ResourceDirectory.GetFiles(CsvFileName, SearchOption.TopDirectoryOnly);

    foreach (FileInfo CsvFile in CsvFiles)
    {
        using (CsvReader ReadCsv = new CsvReader(new StreamReader(CsvFile.FullName)))
        {
            ReturnContents.AddRange(ReadCsv.GetRecords<T>());
        }
    }

    return ReturnContents;
}