在DataTable中读取行时出现奇怪的行为

时间:2018-02-19 09:10:33

标签: c# winforms

---完全代码基本上我只是将DataTable导出到Csv。

try
{
    DataTable dt_copy = new DataTable();
    dt_copy = records;

    string filePath = exportFileName;
    //DataTableToCsv(dt_copy, exportFileName);

    using (TextWriter sUrl = new StreamWriter(filePath, true, Encoding.Unicode))
    {
        var columnNames = dt_copy.Columns.Cast<DataColumn>()
            .Select(column = "\"" + column.ColumnName.Replace("\"", "\"\"") + "\"")
            .ToArray();                
        sUrl.WriteLine(string.Join("\t", columnNames));
        int x = 0;
        foreach (DataRow row in records.Rows) // Out of Memory Exception Here
        {
            x = x + 1; // This loop never stop rows are 32k and i has reached 3 million +
            var fields = row.ItemArray.Select(field = "\"" + field.ToString().Replace("\"", "\"\"") + "\"").ToArray();
            sUrl.WriteLine(string.Join("\t", fields));
        }
    }

    if (MessageBox.Show("Open File", "Open Excel Sheet ?", MessageBoxButtons.YesNo, MessageBoxIcon.Asterisk) == DialogResult.Yes)
    {
        System.Diagnostics.Process.Start(exportFileName);
    }
}
catch (Exception ex)
{
}

谢谢

2 个答案:

答案 0 :(得分:1)

你得到OutOfMemoryException可能是因为你在那里创建了很多临时对象。请注意....

  • DataRow.ItemArray为每一行创建一个新的Object[]
  • field.ToString为每个字段(对象)创建一个新字符串,
  • String.Replace为每个其他字符串创建一个新字符串
  • ToArray创建所有已替换列的新数组
  • String.Join创建StringBuilder并附加数组的所有列

如果您只想输出修改后的字段,则效率更高:

var columns = records.Columns.Cast<DataColumn>().ToArray();
foreach (DataRow row in records.Rows)
{
    var newFields = columns.Select(c => $@"""{row.Field<string>(c)}""");
    sUrl.WriteLine(string.Join("\t", newFields));
}

这假设所有列都是字符串,否则它无论如何都没有意义。

答案 1 :(得分:0)

我百分百肯定。 foreach不是问题。

请删除var fields = row.ItemArray.Select(field = "\"" + field.ToString().Replace("\"", "\"\"") + "\"").ToArray(); sUrl.WriteLine(string.Join("\t", fields));并检查。

但如果你仍然遇到这个问题,那么检查一个条件来打破循环

int x = 0;
    foreach (DataRow row in records.Rows) // Out of Memory Exception Here
    {
        x = x + 1;
        if(x > records.Rows.Length)
        {
          break; 
        }
        var fields = row.ItemArray.Select(field = "\"" + field.ToString().Replace("\"", "\"\"") + "\"").ToArray();
        sUrl.WriteLine(string.Join("\t", fields));
    }