大型数据表到.net中特定大小的多个csv文件

时间:2017-01-15 06:38:10

标签: c# .net csv filesplitting

我有一个包含数百万条记录的大型数据表。我需要将其导出为多个特定大小的CSV文件。因此,例如,我选择5MB的文件大小,当我说导出时,数据表将导出到4个大小为5MB的CSV文件,并且由于剩余记录,最后文件大小可能会有所不同。我在这里看了很多解决方案,看看csvhelper库,但所有处理大文件的内容都会根据指定的文件大小分成多个CSV而不是内存数据表中的多个CSV文件。我想在C#中这样做。这方面的任何帮助都会很棒。

由于 杰

2 个答案:

答案 0 :(得分:2)

感谢@ H.G.Sandhagen和@jdweng的投入。目前我已经编写了以下代码来完成所需的工作。我知道它并不完美,如果我们可以预先确定数据表项目数组的长度,肯定可以完成一些增强,如Nick.McDermaid所指出的那样。截至目前,我将使用此代码来解锁我的自我,并在我编写代码时发布最终的优化版本。

public void WriteToCsv(DataTable table, string path, int size)
        {
            int fileNumber = 0;
            StreamWriter sw = new StreamWriter(string.Format(path, fileNumber), false);
            //headers  
            for (int i = 0; i < table.Columns.Count; i++)
            {
                sw.Write(table.Columns[i]);
                if (i < table.Columns.Count - 1)
                {
                    sw.Write(",");
                }
            }
            sw.Write(sw.NewLine);

            foreach (DataRow row in table.AsEnumerable())
            {
                sw.WriteLine(string.Join(",", row.ItemArray.Select(x => x.ToString())));
                if (sw.BaseStream.Length > size) // Time to create new file!
                {
                    sw.Close();
                    sw.Dispose();
                    fileNumber ++;
                    sw = new StreamWriter(string.Format(path, fileNumber), false);
                }
            }

            sw.Close();
        }

答案 1 :(得分:0)

我遇到了类似的问题,这就是我使用CsvHelper解决的方法。

可以轻松地将答案修改为使用DataTable作为源。

public void SplitCsvTest()
{

  var inventoryRecords = new List<InventoryCsvItem>();

  for (int i = 0; i < 100000; i++)
  {
    inventoryRecords.Add(new InventoryCsvItem { ListPrice = i + 1, Quantity = i + 1 });
  }

  const decimal MAX_BYTES = 5 * 1024 * 1024; // 5 MB

  List<byte[]> parts = new List<byte[]>();

  using (var memoryStream = new MemoryStream())
  {
    using (var streamWriter = new StreamWriter(memoryStream))
    using (var csvWriter = new CsvWriter(streamWriter))
    {
      csvWriter.WriteHeader<InventoryCsvItem>();
      csvWriter.NextRecord();

      csvWriter.Flush();
      streamWriter.Flush();

      var headerSize = memoryStream.Length;
      foreach (var record in inventoryRecords)
      {

        csvWriter.WriteRecord(record);
        csvWriter.NextRecord();

        csvWriter.Flush();
        streamWriter.Flush();

        if (memoryStream.Length > (MAX_BYTES - headerSize))
        {
          parts.Add(memoryStream.ToArray());

          memoryStream.SetLength(0);
          memoryStream.Position = 0;

          csvWriter.WriteHeader<InventoryCsvItem>();
          csvWriter.NextRecord();
        }
      }

      if (memoryStream.Length > headerSize)
      {
        parts.Add(memoryStream.ToArray());
      }
    }


  }

  for(int i = 0; i < parts.Count; i++)
  {
    var part = parts[i];

    File.WriteAllBytes($"C:/Temp/Part {i + 1} of {parts.Count}.csv", part);
  }
}