StringBuillder.Tostring()抛出内存不足异常

时间:2013-07-27 11:32:58

标签: c# .net string memory-management stringbuilder

即使在我清除了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;
                    }

            }

2 个答案:

答案 0 :(得分:1)

  

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

是的,这看起来似乎有道理。你没有因此而耗尽内存,但你正在遭受碎片化的记忆。 SB将被放置在Larg Object堆上,并且收集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的缓冲区。

答案 1 :(得分:0)

你可以检查长度

if (csvBuilder.Length >= 100000)
{

    sw.Write(csvBuilder.ToString());
    csvBuilder.clear();
    lineCount = 0;
}
csvBuilder.AppendLine(String.Join(fileSeperator, dr.ItemArray));
lineCount++;