【发布时间】:2013-01-17 10:03:59
【问题描述】:
我正在使用 LINQ 解析从 csv 文件读取的大量字符串。 我的代码适用于 100MB 文件。 但是由于堆栈溢出异常而无法超越它。 我正在使用 500MB 文件测试我的代码,其中列表中的字符串数约为 400 万。(500MB csv 文件中大约有 400 万行)
public List<Metrics> MetricsParser(DateTime StartDate, TimeSpan StartTime, DateTime EndDate, TimeSpan EndTime,int dateIndex,int timeIndex)
{
DateTime sd = StartDate;
DateTime ed = EndDate;
TimeSpan st = StartTime;
TimeSpan et = EndTime;
StreamReader streamReader;
List<string> lines = new List<string>();
try
{
streamReader = new StreamReader("file.csv");
lines.Clear();
while (!streamReader.EndOfStream)
lines.Add(streamReader.ReadLine());
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (streamReader != null)
streamReader.Close();
}
IEnumerable<Metrics> parsedFileData = null;
parsedFileData = from line in lines
let log = line.Split(",")
where (!(line.StartsWith("#")) & (line.Length > 0))
let dateVal = _utility.GetDateTime(dateformatType, log[(int)dateIndex], log[(int)timeIndex])
let timeVal = _utility.GetTime(log[(int)timeIndex], timeformatType)
where (dateVal >= new DateTime(sd.Year, sd.Month, sd.Day, st.Hours, st.Minutes, st.Seconds)
& dateVal <= new DateTime(ed.Year, ed.Month, ed.Day, et.Hours, et.Minutes, et.Seconds))
select new Metrics()
{
Date = dateVal,
Metrics1 = log[(int)Metrics1Index],
Metrics2 = (Metrics2Index != null) ? log[(int)Metrics2Index] : "default",
Metrics3 = (log[(int)Metrics3Index] == null || log[(int)Metrics3Index] == "") ? "-" : log[(int)Metrics3Index],
Metrics4 = (log[(int)Metrics4Index] == null || log[(int)Metrics4Index] == "") ? "-" : log[(int)Metrics4Index],
Metrics5 = (log[(int)Metrics5Index] == null || log[(int)Metrics5Index] == "") ? "-" : log[(int)Metrics5Index],
Metrics6 = (log[(int)Metrics6Index] == null || log[(int)Metrics6Index] == "") ? "-" : log[(int)Metrics6Index],
Metrics7 = (log[(int)Metrics7Index] == null || log[(int)Metrics7Index] == "") ? "-" : log[(int)Metrics7Index],
Metrics8 = (log[(int)Metrics8Index] == null || log[(int)Metrics8Index] == "") ? "-" : log[(int)Metrics8Index],
Metrics9 = (log[(int)Metrics9Index] == null || log[(int)Metrics9Index] == "") ? "-" : log[(int)Metrics9Index],
};
return parsedFileData.ToList();
}
任何想法如何用更大的数据完成任务。
我按照一些建议尝试了下面的方法,但它也无法克服堆栈溢出异常!
try
{
streamReader = new StreamReader("file.csv");
while (!streamReader.EndOfStream)
{
var line = streamReader.ReadLine();
if (!(line.StartsWith("#")) & (line.Length > 0))
{
var log = line.Split(",");
var dateVal = _utility.GetDateTime(dateformatType, log[(int)dateIndex], log[(int)timeIndex]);
parsedData.Add(
new Metrics()
{
Date = dateVal,
Metrics1 = log[(int)Metrics1Index],
Metrics2 = (Metrics2Index != null) ? log[(int)Metrics2Index] : "default",
Metrics3 = (log[(int)Metrics3Index] == null || log[(int)Metrics3Index] == "") ? "-" : log[(int)Metrics3Index],
Metrics4 = (log[(int)Metrics4Index] == null || log[(int)Metrics4Index] == "") ? "-" : log[(int)Metrics4Index],
Metrics5 = (log[(int)Metrics5Index] == null || log[(int)Metrics5Index] == "") ? "-" : log[(int)Metrics5Index],
Metrics6 = (log[(int)Metrics6Index] == null || log[(int)Metrics6Index] == "") ? "-" : log[(int)Metrics6Index],
Metrics7 = (log[(int)Metrics7Index] == null || log[(int)Metrics7Index] == "") ? "-" : log[(int)Metrics7Index],
Metrics8 = (log[(int)Metrics8Index] == null || log[(int)Metrics8Index] == "") ? "-" : log[(int)Metrics8Index],
Metrics9 = (log[(int)Metrics9Index] == null || log[(int)Metrics9Index] == "") ? "-" : log[(int)Metrics9Index],
}
);
}
}
}
感谢您的想法!
【问题讨论】:
-
使用通用
foreach/for循环不使用LINQ,我相信它会更快、更简单、更稳定。此外,在如此多的项目上,您应该更加小心地执行代码的每一点,因为即使是很小的事情也会显着降低性能,因此请仔细考虑铸造和创建新对象 -
如果您可以单独处理数据,请拆分数据,但由于 linq 使用相当多的内存,您当然仍然可以按照 sll 的建议进行