读取文件的最后30,000行
如果有一个csv文件,其数据会不时增加。 现在我需要做的是阅读最后30,000行。
代码:
string[] lines = File.ReadAllLines(Filename).Where(r => r.ToString() != "").ToArray(); int count = lines.Count(); int loopCount = count > 30000 ? count - 30000 : 0; for (int i = loopCount; i < lines.Count(); i++) { string[] columns = lines[i].Split(','); orderList.Add(columns[2]); }
它工作正常,但问题是
File.ReadAllLines(Filename)
阅读导致性能不足的完整文件。 我想要它只读取最后30,000行迭代整个文件。
PS:我正在使用.Net 3.5。 Files.ReadLines()在.Net 3.5中不存在
您可以使用File.ReadLines()
方法而不是使用File.ReadAllLines()
来自MSDN: File.ReadLines()
ReadLines和ReadAllLines方法的不同之处如下:
使用ReadLines时,可以在返回整个集合之前开始枚举字符串集合; 当您使用ReadAllLines时,必须等待返回整个字符串数组才能访问该数组。因此,当您使用非常大的文件时 , ReadLines可以更高效。
解决方案1 :
string[] lines = File.ReadAllLines(FileName).Where(r => r.ToString() != "").ToArray(); int count = lines.Count(); List orderList = new List (); int loopCount = count > 30000 ? 30000 : 0; for (int i = count-1; i > loopCount; i--) { string[] columns = lines[i].Split(','); orderList.Add(columns[2]); }
解决方案2:如果您正在使用.NET Framework 3.5,如下面的评论所述,您不能使用File.ReadLines()
方法,因为它自.NET 4.0
以来是可用的。
您可以使用StreamReader,如下所示:
List lines = new List (); List orderList = new List (); String line; int count=0; using (StreamReader reader = new StreamReader("c:\\Bethlehem-Deployment.txt")) { while ((line = reader.ReadLine()) != null) { lines.Add(line); count++; } } int loopCount = (count > 30000) ? 30000 : 0; for (int i = count-1; i > loopCount; i--) { string[] columns = lines[i].Split(','); orderList.Add(columns[0]); }
您可以使用File.ReadLines
,您可以在返回整个集合之前开始枚举字符串集合。
之后,您可以使用linq
使事情变得更加容易。 Reverse
将反转收集顺序, Take
将采用n
个项目。 现在再次使用Reverse
以原始格式获取最后n
行。
var lines = File.ReadLines(Filename).Reverse().Take(30000).Reverse();
如果您使用的是.NET 3.5或更早版本,则可以创建自己的方法,其工作方式与File.ReadLines
相同。 这是最初由@Jon编写的方法的代码
public IEnumerable ReadLines(string file) { using (TextReader reader = File.OpenText(file)) { string line; while ((line = reader.ReadLine()) != null) { yield return line; } } }
现在你可以在这个函数上使用linq
,就像上面的语句一样。
var lines = ReadLines(Filename).Reverse().Take(30000).Reverse();
问题是你不知道从哪里开始读取文件以获得最后30,000行。 除非您想要维护单独的线偏移索引,否则您可以从开始计数行读取文件,仅保留最后30,000行,或者您可以从末尾计数行开始向后。 如果文件非常大并且您只需要几行,则最后一种方法可以有效。 但是,30,000似乎不是“几行”所以这里是一种从一开始就读取文件并使用队列来保留最后30,000行的方法:
var filename = @" ... "; var linesToRead = 30000; var queue = new Queue(); using (var streamReader = File.OpenText(fileName)) { while (!streamReader.EndOfStream) { queue.Enqueue(streamReader.ReadLine()); if (queue.Count > linesToRead) queue.Dequeue(); } }
现在您可以访问存储在queue
。 此类实现IEnumerable
允许您使用foreach
迭代行。 但是,如果要随机访问,则必须使用ToArray
方法将队列转换为数组,这会增加计算的开销。
该解决方案在内存方面是高效的,因为必须在内存中保留最多30,000行,并且垃圾收集器可以在需要时释放任何额外的行。 使用File.ReadAllLines
会立即将所有行拉入内存,这可能会增加进程所需的内存。
或者我有一个不同的意识形态。
尝试将csv拆分为AD,EG等类别,并访问您需要的第一个字符。
或者您可以使用entites计数分割数据。 例如,每个文件将包含15.000个entites。 还有一个文本文件,其中包含有关入侵和位置的微小数据。
Txt文件:
entitesID | inWhich.Csv ....