【问题标题】:stringbuiler save to CSV file out of memorystringbuilder 保存到 CSV 文件内存不足
【发布时间】:2016-06-09 20:27:21
【问题描述】:

我需要将大型数据表(5000 行和 8880 列)保存到 CSV 文件。所以我先将DataTable 保存到StringBuilder,然后使用File.WriteAllText 保存到文件。但是由于表的大小,它给了我内存不足异常。我正在考虑使用StreamWriter。谁能帮忙改用StreamWriter

谢谢!

 StringBuilder sb = new StringBuilder();

        string[] CSVcolumnNames = sortedDT.Columns.Cast<DataColumn>().
                                          Select(column => column.ColumnName).
                                          ToArray();
        sb.AppendLine(string.Join(",", CSVcolumnNames));

        foreach (DataRow row in sortedDT.Rows)
        {
            string[] fields = row.ItemArray.Select(field => field.ToString()).
                                            ToArray();
            sb.AppendLine(string.Join(",", fields));
        }

        File.WriteAllText(CSVpath, sb.ToString());

【问题讨论】:

  • 简答:Ctrl-H StreamBuilder -> StreamWriter。 Ctrl-H Append-> Write。修复文件名,删除最后一行。完成。

标签: c# csv datatable stringbuilder


【解决方案1】:

不要使用File.WriteAllText(),它需要所有内存中的数据,改用File.WriteAllLines()(它需要一行的内存> 仅):

var source = sortedDT.Rows
  .OfType<DataRow>() 
  .Select(row => String.Join(",", row.ItemArray));

File.WriteAllLines(CSVpath, source);

如您所见,File.WriteAllLines 为您完成所有工作,您不必使用StreamWriter。如果您想添加标题(列名称):

var columnNames = String.Join(",", sortedDT.Columns
  .OfType<DataColumn>()
  .Select(column => column.ColumnName));

var data = sortedDT.Rows
  .OfType<DataRow>() 
  .Select(row => String.Join(",", row.ItemArray));

var source = new String[] {columnNames}
  .Concat(data);

File.WriteAllLines(CSVpath, source);

【讨论】:

  • @Daniel:唯一的内存问题可以来自sortedDT,解决方案的请求是仅一行/行的内存。
【解决方案2】:

试试这个已经过测试并且工作正常:

       using System.IO;

        using (var sw = new StreamWriter(CSVpath))
        {
            sw.WriteLine(string.Join(",", sortedDT.Columns.Cast<DataColumn>().Select(column => column.ColumnName)));

            foreach (DataRow row in sortedDT.Rows)
            {
               sw.WriteLine(string.Join(",", row.ItemArray.Select(field => field.ToString())));

            }
        }

此代码将fields 行写入名称为CSVpath 的文件。先列名,后列值

【讨论】:

  • 不需要调用 ToArray 吗? string.Join 适用于 IEnumerable。为了提高效率 - 也许避免 string.join 也是个好主意
  • 非常感谢您的发帖。我看到你把string[]改成var,有什么目的吗?
  • @Daniel 只是重构。 string.Join 接受IEnumerable 接口所以不需要使用ToArray() 方法。对于您的性能问题,可以避免不必要的工作。我对此进行了测试,它可以按您的意愿完美运行
  • 非常感谢!我会测试并告诉你
猜你喜欢
  • 1970-01-01
  • 2013-11-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-29
  • 1970-01-01
  • 1970-01-01
  • 2014-11-12
  • 1970-01-01
相关资源
最近更新 更多