我想在C#中读取.txt文件,但我不会同时读取所有行。例如,考虑500行文本文件。我希望一个函数运行25次,每次读取20行。在第一次调用函数时,将读取从1到20的行,第二次调用它时,将读取21-40。
下面的简单代码在c ++中执行此操作,但我不知道如何在C#中实现它:
string readLines(ifstream& i)
{
string totalLine="", line = "";
for(int i = 0; i < 20; i++){
getline(i, line);
totalLine += line;
}
return totalLine;
}
int main()
{
// ...
ifstream in;
in.open(filename.c_str());
while(true){
string next20 = readLines(in);
// so something with 20 lines.
}
// ...
}
答案 0 :(得分:3)
这里有各种选择,但一种简单的方法是:
using (var reader = File.OpenText("file.txt"))
{
for (int i = 0; i < 25; i++)
{
HandleLines(reader);
}
}
...
private void HandleLines(TextReader reader)
{
for (int i = 0; i < 20; i++)
{
string line = reader.ReadLine();
if (line != null) // Handle the file ending early
{
// Process the line
}
}
}
答案 1 :(得分:2)
如果尝试拨打LineRead()
最少次数并且您希望最小内存使用量,您可以先对文件中的行进行索引:
- 解析文件一次,索引
FileStream
中每行的位置。- 仅在所需位置呼叫 ReadLine()。
醇>
例如:
// Parse the file
var indexes = new List<long>();
using (var fs = File.OpenRead("text.txt"))
{
indexes.Add(fs.Position);
int chr;
while ((chr = fs.ReadByte()) != -1)
{
if (chr == '\n')
{
indexes.Add(fs.Position);
}
}
}
int minLine = 21;
int maxLine = 40;
// Read the line
using (var fs = File.OpenRead("text.txt"))
{
for(int i = minLine ; i <= maxLine ; i++)
{
fs.Position = indexes[ i ];
using (var sr = new StreamReader(fs))
Console.WriteLine(sr.ReadLine());
}
干杯!
答案 2 :(得分:1)
您可以像这样编写Batch()方法:
public static IEnumerable<string> Batch(IEnumerable<string> input, int batchSize)
{
int n = 0;
var block = new StringBuilder();
foreach (var line in input)
{
block.AppendLine(line);
if (++n != batchSize)
continue;
yield return block.ToString();
block.Clear();
n = 0;
}
if (n != 0)
yield return block.ToString();
}
并称之为:
string filename = "<Your filename goes here>";
var batches = Batch(File.ReadLines(filename), 20);
foreach (var block in batches)
{
Console.Write(block);
Console.WriteLine("------------------------");
}
答案 3 :(得分:0)
糟糕。 GroupBy不会懒惰地评估,所以这将贪婪地消耗整个文件
<击> 撞击>
<击>var twentyLineGroups =
File.ReadLines(somePath)
.Select((line, index) => new {line, index})
.GroupBy(x => x.index / 20)
.Select(g => g.Select(x => x.line));
foreach(IEnumerable<string> twentyLineGroup in twentyLineGroups)
{
foreach(string line in twentyLineGroup)
{
//tada!
}
}
击> <击> 撞击>