从CSV中读取所选行

时间:2014-10-28 09:27:59

标签: c# performance csv readline

我有一个非常大的CSV文件,大约有1,000,000行,它需要大约500 MB的内存。我不必阅读所有文件。我想从文件中读取每百分之一行。我试图通过ReadLines来做,但它确实很慢,ReadAllLines更快。

我的代码:

for (int i = 0; i < 10000; i++)
{
   tableOfString[i]=File.ReadLines("TestCSV.csv").Skip(i*100).Take(1).First();
   //or
   tableOfString[i] = File.ReadLines("TestCSV.csv").ElementAtOrDefault(i*100);
}

我读到了一些读者:

有人有解决方案吗?我想只读取CSV中的某些行,而不是整个文件。

3 个答案:

答案 0 :(得分:2)

ReadLines并不慢。问题是您要在每次迭代中将文件重新读取到所需的行 。 (当i = 1时,你读0-100行...当i = 2时,你读0-200行等等。)

您应该避免多次调用File.ReadLines。换句话说,只打开文件一次并使用Where过滤掉您不想要的行。所以试试这个:

var filteredLines = File.ReadLines("TestCSV.csv")
    .Select((Text, Index) => new {Text, Index})
    .Where(x => x.Index % 100 == 0);

foreach(var line in filteredLines)
{
    tableOfString[line.Index] = line.Text;
}  

不确定你是如何创建或使用tableOfString的,但是如果它仅用于获取这些行,那么你可以直接将你的linq查询转换为数组(你不必填充) for循环中的数组:

 var tableOfString = File.ReadLines("TestCSV.csv")
    .Where((x, i) => i % 100 == 0)
    .ToArray();

答案 1 :(得分:1)

根据您想要的代码

CSV文件的

0th, 100th, 200th ... 1000000th行并将其存储在tableOfString[]

你可以这样做:

  tableOfString = File
    .ReadLines("TestCSV.csv")
    .Where((line, index) => (index % 100) == 0)
    .ToArray();

在循环中重新打开文件(速度很慢)意味着很大的开销

答案 2 :(得分:0)

首先,如果您不想将完整文件加载到内存中,则File.ReadLines和File.ReadAllLines不起作用。

如果您只想将文件的几个字节读入RAM,我建议您使用File.OpenRead,然后将所需的部分读入缓冲区。与How can I read/stream a file without loading the entire file into memory?一样。

但是,除了你有问题,你不能跳过99行,只读每100行。如果要实现此功能,则需要知道每行的大小,以便在读取方法中设置偏移量。

最新版本是使用File.ReadAllLine,而不是迭代字符串数组或使用Linq。