0

我正在尝试将 SQL 表数据导出到 C# 代码中带有“~”分隔符的文本文件。当数据很小时,它很好。当它很大时,它会抛出内存不足异常。

我的代码:

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 命令中是否有更好的方法来执行此操作?

4

2 回答 2

1

如果没有使用 ~ 分隔符格式的特定原因,您可以尝试使用 DataTable 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,然后重新打开并附加到现有文本。

于 2011-01-24T02:51:40.370 回答
0

我意识到这个问题已有多年历史,但我最近遇到了类似的问题。解决方案:简而言之,我认为您在使用 Windows 大对象堆时遇到了问题。相关链接: https ://www.simple-talk.com/dotnet/.net-framework/the-dangers-of-the-large-object-heap/

总结一下上面的文章:当您分配超过 85K 长的内存块时(如果 DataTable 中的值足够大,这似乎可能发生在 StreamWriter 对象的幕后),它们会进入一个单独的堆,即大对象堆 (LOH)。LOH 中的内存块在其生命周期到期时通常会被释放,但堆没有被压缩。最终结果是 aSystem.OutOfMemoryException被抛出,并不是因为实际上没有足够的内存,而是因为在某个时刻堆中没有足够的连续内存。

如果您使用的是 .NET framework 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()是个坏主意,并且会减慢你的应用程序——他们是对的。我只是不知道更好的方法来处理这个问题。

于 2015-01-22T19:20:08.307 回答