2011-01-24 79 views
0

我試圖將SQL表數據導出到C#代碼中具有'〜'分隔符的文本文件。 當數據很小時很好。當它很大時,它會拋出一個內存不足的例外。將表數據導出爲文本文件+ C#+ SQL Server

我的代碼:

public static void DataTableToTextFile(DataTable dtToText, string filePath) 
{ 
    int i = 0; 
    StreamWriter sw = null; 

    try 
    { 
     sw = new StreamWriter(filePath, false); /*For ColumnName's */ 
     for (i = 0; i < dtToText.Columns.Count - 1; i++) 
     { 
      sw.Write(dtToText.Columns[i].ColumnName + '~'); 
     } 
     sw.Write(dtToText.Columns[i].ColumnName + '~'); 
     sw.WriteLine(); /*For Data in the Rows*/ 

     foreach (DataRow row in dtToText.Rows) 
     { 
      object[] array = row.ItemArray; 
      for (i = 0; i < array.Length - 1; i++) 
      { 
       sw.Write(array[i].ToString() + '~'); 
      } 
      sw.Write(array[i].ToString() + '~'); 
      sw.WriteLine(); 
     } 
     sw.Close(); 
    } 
    catch (Exception ex) 
    { 
     throw new Exception(""); 
    } 
} 

有沒有更好的方式在存儲過程或BCP命令來做到這一點?

+0

你有沒有試過寫作說1000行,關閉然後打開文件? – griegs 2011-01-24 01:15:04

回答

1

如果有使用〜定界符格式沒有具體的原因,你可以嘗試使用數據表功能中WriteXML(http://msdn.microsoft.com/en-us/library/system.data.datatable.writexml.aspx

例如: dtToText.WriteXml( 「C:\ data.xml中」)

如果您需要將這些內容轉換回一個DataTable後,你可以使用的ReadXml(http://msdn.microsoft.com/en-us/library/system.data.datatable.readxml.aspx

如果你真的需要使現有的代碼工作,我可能會嘗試關閉並在對StreamWriter的調用Dispose設置間隔,然後重新打開並追加到existin g文本。

0

我意識到這個問題已經過去了幾年,但我最近經歷過類似的問題。解決方案:簡單地說,我認爲你遇到了Windows大對象堆的問題。一個相關鏈接: https://www.simple-talk.com/dotnet/.net-framework/the-dangers-of-the-large-object-heap/

綜上所述文章:當您分配的內存大於85K長塊(這似乎可能在你的StreamWriter對象在幕後發生,如果在你的數據表中的值足夠大),他們進入一個單獨的堆,大對象堆(LOH)。 LOH中的內存塊通常在其生命週期到期時解除分配,但堆未壓縮。最終的結果是引發了一個System.OutOfMemoryException,這並不是因爲沒有足夠的內存,而是因爲堆中沒有足夠的內存連接。

如果您使用.NET框架4.5.1或更高版本(這將不會在Visual Studio 2010中或工作前,它可能會在VS2012工作),你可以使用這個命令:

System.Runtime.GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce; 

該命令強制LOH壓縮發生在下一次垃圾回收。只需將該命令作爲函數的第一行;每次調用該函數時都會將其設置爲CompactOnce,這會在函數調用後的某個不確定點導致LOH壓縮。

如果你沒有.NET 4.5.1,它會變得更醜。問題是內存分配不明確;它最有可能發生在StreamWriter的幕後。嘗試調用GC.Collect(),強制垃圾收集,可能每隔3次調用一次該函數。

警告:很多人會建議直接調用GC.Collect()是一個壞主意,會降低應用程序的速度 - 而且他們是對的。我只是不知道解決這個問題的更好方法。

相關問題