我正在尝试将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命令中有更好的方法吗?
答案 0 :(得分: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,然后重新打开并附加到现有文本。
答案 1 :(得分:0)
我意识到这个问题已有数年之久,但我最近遇到了类似的问题。解决方案:简而言之,我认为您遇到了Windows大对象堆的问题。相关链接: https://www.simple-talk.com/dotnet/.net-framework/the-dangers-of-the-large-object-heap/
总结上面的文章:当你分配超过85K长的内存块时(如果你的DataTable中的值足够大,这似乎可能发生在你的StreamWriter对象的幕后),它们会进入一个单独的堆,大对象堆(LOH)。 LOH中的内存块通常在其生存期到期时被释放,但堆不会被压缩。最终结果是抛出System.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()
是一个坏主意,会减慢您的申请速度 - 而且他们是对的。我只是不知道更好的方法来处理这个问题。