主要是由于可读性,我使用以下代码
List<string[]>,以便以后能够使用LINQ和/或PLINQ然而,这个过程大约需要4-5秒,这只是简单地说太长了。关于如何改进以下内容(甚至可能替换它),有什么建议吗?
var query = (from x in Directory.GetFiles(_path, "*.csv").AsParallel()
where x.Contains(dateTime)
select x).First();
#region Read CSV File
List<string[]> _tempList = new List<string[]>();
FileStream stream = new FileStream(query, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
using (StreamReader reader = new StreamReader(stream, Encoding.Default, true, 1024))
{
string currentLine;
while ((currentLine = reader.ReadLine()) != null)
{
string[] temp = currentLine.Split(new char[] { ',' }, StringSplitOptions.None);
_tempList.Add(temp);
}
}
#endregionCSV文件内的顺序很重要--该文件将包含(2000-7000) x25项之间的内容。
CSV文件有几个我不感兴趣的字段--我不一定需要它们在我的List<string[]> (或string[][])中。我尝试使用类似于以下伪代码的LINQ语句对它们进行筛选:
var query = from x in MyListOfStringArray
select new {Col1 = x[1] , Col2 = c[4]}.ToArray();这种方法导致了一种奇怪的查询类型--而且非常慢(我将有一个具有大约9-11属性的数组)。对第二个问题有什么想法吗?
发布于 2014-09-05 01:53:55
var query =( Directory.GetFiles(_path,“*.csv”)中的x).AsParallel(),其中x.Contains(dateTime)选择x).First();
如果Directory.GetFiles(_path, "*.csv")不返回任何文件( where x.Contains(dateTime) ),那么这一行就会被一个可能有点令人失望/令人惊讶的InvalidOperationException炸开。
我发现使用100%的方法语法可以更清楚地查询--这将是等价的:
var query = Directory.GetFiles(_path, "*.csv")
.AsParallel()
.Where(name => name.Contains(dateTime))
.First();query这个名字是错误的/误导的。如果它是一个IQueryable<string> (即直到.Where()调用之后),这将是一个查询.但事实并非如此,var实际上代表string,您所称的query实际上是一个fileName:.First()将查询物化,并返回第一个元素.或者抛出一个异常。
最好调用.FirstOrDefault(),如果没有符合搜索条件的文件,这将使结果null。
我不明白您为什么在这里使用var,因为您在其他地方都使用显式类型。特别是因为var只是一个string。不过,别误会我:我更喜欢在这里看到var .还有其他地方。
#区域读取CSV文件
在方法中使用#region可以清楚地表示,您的方法正在做不止一件事情。每当你这样做的时候,你就错过了一个重构的机会。考虑在这里提取一种方法:
private string GetFileName(string formattedDateTime)
{
return Directory.GetFiles(_path, "*.csv")
.AsParallel()
.Where(name => name.Contains(formattedDateTime))
.FirstOrDefault();
}(缺乏推荐传入实际DateTime的上下文)
这就给您留下了一个方法(希望)现在只有这个#region块,它现在完全是多余的,可以被丢弃(如果还有更多的方法,请根据需要提取方法)。
上面说..。
FileStream stream =新FileStream(查询、FileMode.Open、FileAccess.Read、FileShare.ReadWrite);使用(StreamReader reader =新StreamReader(StreamReader,Encoding.Default,true,1024))
配置StreamReader也会干净地关闭和释放FileStream,但这还远远不是显而易见的,除非您知道这一点,并且如果乔恩·斯基特说这是最好的做法将它放在自己的using块中,那么我只能同意他的意见。
您的代码可以使用一个变量(在循环正文之外声明)作为值分隔符:您正在为正在读取的每一行创建一个新的字符数组!
char[] separator = new char[] { ',' };或者更简洁地说:
var separator = new[] { ',' };这使得temp分配更加清晰/更清晰:
string[] temp = currentLine.Split(separator, StringSplitOptions.None);看看currentLine,我们还不清楚这里发生了什么:
while ((currentLine = reader.ReadLine()) != null)使用赋值的结果很少会产生容易读的代码。我喜欢它如何巧妙地将下一行读入currentLine并验证它是否是null值.所以我不确定我是否会建议重写那部分。
当您阅读完文件时,还不清楚您的List<string[]>发生了什么,所以我假设您只是返回它。在这种情况下,您可以考虑使用yield来处理结果:
private IEnumerable<string[]> ReadCsv(string fileName)
{
char[] separator = new[] { ',' };
string currentLine;
using (var stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (var reader = new StreamReader(stream, Encoding.Default, true, 1024))
{
while ((currentLine = reader.ReadLine()) != null)
{
yield return currentLine.Split(separator, StringSplitOptions.None);
}
}
}https://codereview.stackexchange.com/questions/61973
复制相似问题