sb = new StringBuilder(1024 * 1024 * 1024)>抛出'System.OutOfMemoryException'

时间:2013-12-11 01:14:58

标签: c# mysql out-of-memory stringbuilder

我需要在循环中附加大量字符串,这将创建一个非常长的字符串。
1GB应足够长以存储字符串,因此我这样做:

var sb = new StringBuilder(1024 * 1024 * 1024);

但收到此错误

'System.OutOfMemoryException' was thrown

任何追加长字符串的建议吗?

我正在为MySQL数据库编写备份工具。这些工具将从数据库导出数据并写入文本文件。数据包含BLOB和TEXT数据类型。所以,期待很长的字符串。

这是代码:代码更新1

var conn = new MySqlConnection(Program.ConnectionString);
var cmd = new MySqlCommand();
cmd.Connection = conn;
conn.Open();

cmd.CommandText = selectSQL;

MySqlDataReader rdr = cmd.ExecuteReader();

while (rdr.Read())
{
    var sb = new StringBuilder(1024 * 1024 * 1024);
    for (int i = 0; i < rdr.FieldCount; i++)
    {
        if (sb.Length > 0)
            sb.AppendFormat(separator);

        if (rdr[i].GetType() == typeof(byte[]))
        {
            sb.AppendFormat(ConvertByteArrayToHexString((byte[])rdr[i]));
        }
        else
            sb.AppendFormat(rdr[i] + "");
    }
    WriteToFile(sb.ToString());
}

conn.Close();

3 个答案:

答案 0 :(得分:6)

使用文件流编写长文件。任何时候都不需要将完整的字符串保留在内存中。

答案 1 :(得分:4)

根据Windows虚拟内存的方式以及.NET运行时的工作原理,内存不足错误可能由多种原因引起。

你真的需要一次将所有内容都转储到StringBuilder中吗?如果您正在写入文件,则可以一次分段操作。

使用类似的东西作为起点:     int bufferSize = 65536;

using (StreamWriter sw = new StreamWriter("filename", true, System.Text.Encoding.UTF8, bufferSize))
{
    while(!finished)
    {
        string data = "foo"; //get next data here...
        sw.Write(data);
    }
}

`

参考文献:What consumes less resources and is faster File.AppendText or File.WriteAllText storing first in StringBuilder?

答案 2 :(得分:4)

你没有要求StringBuilder有足够的容量来存储1 GB - 你已经要求一个有足够容量存储1024 * 1024 * 1024字符的字符串,这需要(大约)2 GB的内存。它小于最大字符串长度(2 ^ 31-1个字符),但大于32位进程中可用的堆空间。

您可能不需要具有这种容量的StringBuilder - 其他人的答案也在讨论这个问题。假设您需要一个巨大的字符串,您绝对不需要预先分配具有该大小的StringBuilder。只需创建一个StringBuilder,然后让它grow on its own

var sb = new StringBuilder();

或预先分配更合理的内容,如果您知道您将拥有大量数据:

var sb = new StringBuilder(1024 * 1024);