我一直在为我的一个朋友做一个小程序,他有一个非常大的文件,我读到了一个数据网格视图>修改数据>导出到csv。直到最近他让我对数据的导出方式做了一些改变,我设法使一切工作都相关。出于某种原因,我在运行此函数时遇到Out of Memory异常。
library(dplyr)
team.stats %>%
left_join(df.2017, by = c("team", "year")) %>%
left_join(df.2016, by = c("team", "year")) %>%
mutate(ppg = coalesce(ppg.x, ppg.y)) %>%
select(-ppg.x, -ppg.y)
#> team year ppg
#> 1 Duke 2017 65
#> 2 UVA 2017 74
#> 3 UNC 2017 53
#> 4 Xavier 2017 63
#> 5 Duke 2016 68
#> 6 UVA 2016 61
#> 7 UNC 2016 82
#> 8 Xavier 2016 71
private void ExportData(int fileNum = 1, int rowCount = 0)
{
int lastRow = rowCount;
if (!Directory.Exists(ExportPath + dataFilePath.Name))
Directory.CreateDirectory(ExportPath + dataFilePath.Name);
StreamWriter sw = new StreamWriter(ExportPath + dataFilePath.Name + @"\" + dataFilePath.Name + "_" + fileNum + ".csv");
//var headers = dataGridView1.Columns.Cast<DataGridViewColumn>();
//sw.WriteLine(string.Join(",", headers.Select(column => "\"" + column.HeaderText + "\"").ToArray()));
sw.WriteLine("Unit,UPC,Brand,Vendor,List Cost,QTY,Price,Description,Attribute 1,Attribute 2," +
"Descriptor 1,Descriptor 2,Descriptor 3,Descriptor 4,Descriptor 5,Descriptor 6,Descriptor 7,Descriptor 8");
for (int i = 0; i < 50000; i++)
{
rowCount = lastRow + i;
if (rowCount >= dataGridView1.RowCount)
break;
var cells = dataGridView1.Rows[rowCount].Cells.Cast<DataGridViewCell>();
sw.WriteLine(string.Join(",", cells.Select(cell => "\"" + cell.Value + "\"").ToArray()));
}
sw.Close();
sw.Dispose();
lastRow = rowCount + 1;
if (lastRow < dataGridView1.RowCount - 1)
ExportData(fileNum + 1, lastRow);
else
{
progressBar1.BeginInvoke(new MethodInvoker(delegate {
progressBar1.Style = ProgressBarStyle.Blocks;
button_OpenDataFile.Enabled = true;
button_ConvertFromRaw.Enabled = true;
button_exportLS.Enabled = true;
Console.WriteLine("[Main] Export complete.");
}));
}
}
似乎是错误发生的那一行。
任何人都可以提供任何有关我做错的见解吗?
谢谢!
答案 0 :(得分:0)
执行此实验:将代码转换为循环,而不是使用递归:
private void ExportData()
{
//You only need to do this once, take it out of the loop.
if (!Directory.Exists(ExportPath + dataFilePath.Name))
Directory.CreateDirectory(ExportPath + dataFilePath.Name);
var fileNum = 0;
var rowCount = 0;
while (rowCount < dataGridView1.RowCount)
{
fileNum = fileNum + 1;
using (StreamWriter sw = new StreamWriter(ExportPath + dataFilePath.Name + @"\" + dataFilePath.Name + "_" + fileNum + ".csv")
{
sw.WriteLine("Unit,UPC,Brand,Vendor,List Cost,QTY,Price,Description,Attribute 1,Attribute 2," +
"Descriptor 1,Descriptor 2,Descriptor 3,Descriptor 4,Descriptor 5,Descriptor 6,Descriptor 7,Descriptor 8");
for (int i = 0; i < 50000; i++)
{
rowCount = rowCount + 1;
if (rowCount >= dataGridView1.RowCount)
break;
var cells = dataGridView1.Rows[rowCount].Cells.Cast<DataGridViewCell>();
sw.WriteLine(string.Join(",", cells.Select(cell => "\"" + cell.Value + "\"").ToArray()));
}
} //sw.Close() and sw.Dispose() not needed because of the 'using'. You may want to do sw.Flush().
}
//The 'else' part of your original recursive method
progressBar1.BeginInvoke(new MethodInvoker(delegate {
progressBar1.Style = ProgressBarStyle.Blocks;
button_OpenDataFile.Enabled = true;
button_ConvertFromRaw.Enabled = true;
button_exportLS.Enabled = true;
Console.WriteLine("[Main] Export complete.");
}));
}
错误会消失吗?可能是。递归在堆栈中使用大量内存,并且在递归结束时再次向上移动时不会释放它。您收到错误的行恰好尝试将csv文件中整行的内容添加到内存中。如果内存已经几乎已经满了递归堆栈,那么这可能是导致内存不足异常的最后一次丢弃。
我删除了一些似乎多余的累加器变量,我希望我没有弄乱循环的范围。
我从循环中删除了CreateDirectory
,并为using
添加了StreamWriter
语句。我不认为这些是你的错误的原因,因为目录只创建了一次,而你在递归调用之前处理了StreamWriter
,但无论如何如果要确认它,你可以尝试撤消这些更改在非递归代码中逐个查看,并查看错误是否再次发生。
答案 1 :(得分:0)
所以我明白了。
我想迭代通过datagridview只是不是要走的路。
相反,我只是使用我的数据源导出数据。它的速度要快得多......从2分钟到2秒左右。
谢谢大家的帮助!
private void ExportData()
{
//You only need to do this once, take it out of the loop.
if (!Directory.Exists(ExportPath + dataFilePath.Name))
Directory.CreateDirectory(ExportPath + dataFilePath.Name);
var fileNum = 0;
var rowCount = 0;
while (rowCount < dataGridView1.RowCount)
{
fileNum = fileNum + 1;
using (StreamWriter sw = new StreamWriter(ExportPath + dataFilePath.Name + @"\" + dataFilePath.Name + "_" + fileNum + ".csv"))
{
sw.WriteLine("Unit,UPC,Brand,Vendor,List Cost,QTY,Price,Description,Attribute 1,Attribute 2" +
"Descriptor 1,Descriptor 2,Descriptor 3,Descriptor 4,Descriptor 5,Descriptor 6,Descriptor 7,Descriptor 8");
for (int i = 0; i < 50000; i++)
{
rowCount = rowCount + 1;
if (rowCount >= dataGridView1.RowCount)
break;
var s = new string[]
{
"\"" + DATA[rowCount].Unit + "\"",
"\"" + DATA[rowCount].UPC + "\"",
"\"" + DATA[rowCount].Brand + "\"",
"\"" + DATA[rowCount].Vendor + "\"",
"\"" + DATA[rowCount].List_Cost + "\"",
"\"" + DATA[rowCount].Quantity.ToString() + "\"",
"\"" + DATA[rowCount].Price + "\"",
"\"" + DATA[rowCount].Description + "\"",
"\"" + DATA[rowCount].Attribute_1 + "\"",
"\"" + DATA[rowCount].Attribute_2 + "\"",
"\"" + DATA[rowCount].Descriptor_1 + "\"",
"\"" + DATA[rowCount].Descriptor_2 + "\"",
"\"" + DATA[rowCount].Descriptor_3 + "\"",
"\"" + DATA[rowCount].Descriptor_4 + "\"",
"\"" + DATA[rowCount].Descriptor_5 + "\"",
"\"" + DATA[rowCount].Descriptor_6 + "\"",
"\"" + DATA[rowCount].Descriptor_7 + "\"",
"\"" + DATA[rowCount].Descriptor_8 + "\""
};
sw.WriteLine(string.Join(",", s));
sw.Flush();
}
} //sw.Close() and sw.Dispose() not needed because of the 'using'. You may want to do sw.Flush().
}
//The 'else' part of your original recursive method
progressBar1.BeginInvoke(new MethodInvoker(delegate
{
progressBar1.Style = ProgressBarStyle.Blocks;
button_OpenDataFile.Enabled = true;
button_ConvertFromRaw.Enabled = true;
button_exportLS.Enabled = true;
Console.WriteLine("[Main] Export complete.");
}));
}'