0

即使在我清除了 stringbuilder 对象后,我也出现了内存不足的异常。

我想将数据表转换为 CSV,当我尝试将其转换为字符串时出现异常。

代码如下:

        int lineCount = 0;
        const int capacity = 10000000; 
        StringBuilder csvBuilder = new StringBuilder(capacity);
        if (dt != null && dt.Rows.Count > 0)
        {
                    using (var sw = new StreamWriter(FileName, false))
                    {
                        foreach (DataRow dr in dt.Rows)
                        {
                            csvBuilder.AppendLine(String.Join(fileSeperator, dr.ItemArray));
                            lineCount++;
                            if (lineCount >= 100000)
                            {

                                sw.Write(csvBuilder.ToString());
                                csvBuilder.clear();
                                lineCount = 0;
                            }                              

                        }


                        sw.Write(csvBuilder.ToString());
                        csvBuilder.clear();
                        lineCount = 0;
                    }

            }
4

2 回答 2

1

即使在我清除了 stringbuilder 对象后,我也出现了内存不足的异常。

是的,这看起来很合理。您并没有像这样耗尽内存,而是遭受内存碎片的困扰。SB 将被放置在大对象堆上,并且 LOH 被收集但不被压缩。清除 StringBuilder 将无济于事。

解决方案当然很简单:使用较小的缓冲区,或者根本不使用。

//const int capacity = 10000000; 
  const int capacity = 1000000;    // depends on average linelength

//if (lineCount >= 100000)
  if (lineCount >= 1000)

您似乎使用 StringBuilder 来缓冲 I/O,您是否彻底分析过?FileStream 已经缓冲了,当你想帮助你时,你应该瞄准一个 8 - 16 kB 的缓冲区。

于 2013-07-27T11:36:50.377 回答
0

你可以检查长度

if (csvBuilder.Length >= 100000)
{

    sw.Write(csvBuilder.ToString());
    csvBuilder.clear();
    lineCount = 0;
}
csvBuilder.AppendLine(String.Join(fileSeperator, dr.ItemArray));
lineCount++;
于 2013-07-27T11:58:20.657 回答