使用LINQ读取文件前10行

3

请问有人能解释一下如何在LINQ中读取文本文件的前十行吗?

使用StreamReader的代码:

using (var reader = new StreamReader(fileName))
{
    string ListLines = "";
    for (int i = 0; i < 10; i++)
    {
        ListLines[i] = reader.ReadLine();
    }
}
return ListLines;

你有尝试过什么吗?将它张贴出来,这样我们就可以看看并帮助你。 - Abe Miessler
4
你尝试过什么?这很简单,但听起来似乎可能是作业,而你并没有表现出付出努力的迹象。如果你提供更多关于你所尝试过的信息,我相信你会得到有用的回答。 - Jon Skeet
我尝试使用C# - StreamReader,但我想知道是否可以使用LINQ实现。 - Rushabh Shah
这可能会有所帮助;https://dev59.com/4XM_5IYBdhLWcg3wslRW - Dane Balia
4个回答

10

您可以使用:

var lines = File.ReadLines(path).Take(10));

使用 ReadLines 而不是 ReadAllLines,可以从文件中流式传输数据,而不是将整个文件读入内存。如果你仍在使用 C# 3.5 而不是4(当ReadLines被添加时),你可以使用以下实现:

public static IEnumerable<string> ReadLines(string filename)
{
    using (TextReader tr = new StreamReader(filename))
    {
        string nextLine = tr.ReadLine();

        while (nextLine != null)
        {
            yield return nextLine;
            nextLine = tr.ReadLine();
        }
    }
}

File.ReadLines()(以及您手动实现的方法)仍然会读取文件中的每一行,这似乎并没有解决性能问题的关注点。 - itsme86
@itsme86 不,它不会读取文件中的每一行。它会延迟执行,并且由于 Take 调用,它最终只会读取前 10 行。一个简单的方法是使用我的方法,在每次读取行后添加 Console.WriteLine 并查看打印出多少行。 - Servy
啊,现在明白了。+1。 - itsme86
但是,获取未定义时间的资源真的那么聪明吗?如果系统为该文件获取读取锁定,则只要枚举器存在,就没有人能够写入该文件。而这可能需要很长一段时间。这正确吗? - Johannes Egger
1
@Jasd 你可以直接使用ToArrayToList将所有数据读取进来。对于只有10行的情况,这样做是可取的。另外可能会将整个东西放入一个foreach循环中。这意味着同一时间内最多只需要保留一行在内存中。如果你要处理大量数据,那么可能需要这样做。不过如果这样做,你正确地指出,在处理过程中文件将被锁定。 - Servy
+1 你提到了 IEnumerable<string> 的延迟执行特性,但没有提到另一个有趣的方面。如果你多次迭代这个 IEnumerable,它会每次重新打开和遍历文件行;根据你的需求,这可能非常理想(例如,追踪日志文件)或非常烦人。很好的回答。 - devgeezer

6

你的代码已经很优化,可以达到目标:

var list = new List<string>();
using (var reader = new StreamReader(fileName))
{
    for (int i = 0; i < 10; i++)
    {
        list.Add(reader.ReadLine());
    }
}
return list;

或者

using (var reader = new StreamReader(fileName))
{
    for (int i = 0; i < 10; i++)
    {
        yield return reader.ReadLine();
    }
}

或者

var r = File.ReadLines(fileName)
            .Take(10)   // limit to first 10
            .ToArray(); // materialize, if needed

公共静态 IEnumerable<string> GetLine(string fileName) { var lines = File.ReadAllLines(fileName).Take(10); return lines; } // 这是我尝试调用的函数,但它没有读取任何行 - Rushabh Shah
@RushabhShah: 调用ToArray()函数然后 - abatishchev

5

LINQ 风格:

using (var textReader = File.OpenText(fileName))
{
    return Enumerable.Range(1, 10).Select(i => textReader.ReadLine());
}

有趣。聪明的方法是避免读取整个文件以保持性能。 - itsme86
@abatishchev:不,它仍然很简单,并且在必须将所有行加载到内存时比Take(10)获得更好的性能,考虑一下大型文本文件。 - cuongle
只要你从尽可能推迟文件读取的东西中获取,例如ReadLines,那么“Take”就可以了。 - Servy
如果行数少于10行,此代码将导致异常而不是返回所有可用的行。您还将文件读取推迟到using块之外,因此在第一次尝试读取行时,文件将被关闭。 - Servy
@CuongLe 谁说要调用 ReadAllLines 了?我知道我没有,而且我也没有看到其他人在这里的评论中提到它。我特别提到了 ReadLines,它可以正确地推迟执行。 - Servy
显示剩余2条评论

-1

你可能会对这个感兴趣 :)

using (var reader = new StreamReader(filename))
{
    return (from p in Enumerable.Range(0, 10) select reader.ReadLine()).ToList();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接