2013-12-11 38 views
1

我需要在一個循環中追加很多字符串,這會創建一個很長的字符串。
1GB應足夠長,存儲字符串,所以我這樣做:sb = new StringBuilder(1024 * 1024 * 1024)>'System.OutOfMemoryException'被拋出

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(); 
+0

看來,你的JVM是不是配置爲可以訪問2千兆字節的內存(1G字符== 2GB)。 – dasblinkenlight

+2

JVM?這是一個C#問題。 – Nuzzolilo

回答

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?

+0

更新了代碼。令人驚訝的是單線隊員仍然獲得最多選票。 – Nuzzolilo

6

使用文件流寫入長的文件。沒有必要在任何時候將完整的字符串保存在內存中。

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);