从txt文件中读取第二行并保存(C#)

7

我的任务是只读取.txt文件中的第二行,并将其保存为字符串,以便稍后在代码中使用。

文件名为“SourceSetting”。在第1和第2行中我有一些单词

对于第1行,我有以下代码:

string Location;
StreamReader reader = new StreamReader("SourceSettings.txt");
{
    Location = reader.ReadLine();
}
ofd.InitialDirectory = Location;

这很好,但我该如何使其仅读取第二行,以便我可以将其保存为例如:

string Text

1
Location = reader.ReadLine(); Text = reader.ReadLine(); - Lucas Trzesniewski
1
再次调用 ReadLine 吗? - CompuChip
第二,按照定义,意味着在第一之后。因此,如果您调用ReadLine()一次来读取第一行,那么猜猜您如何获得下一行(第二行)? Bingo!您再次调用它...老实说,您怎么会不想尝试这个呢? - musefan
最好接受Tim的解决方案。 - Artiom
谢谢大家!你们帮了我很多,现在我理解得更好了! - Christoph Bethge
5个回答

16
您可以通过不对第一行进行任何操作来跳过它,因此调用ReadLine两次:
string secondLine:
using(var reader = new StreamReader("SourceSettings.txt"))
{
    reader.ReadLine(); // skip
    secondLine = reader.ReadLine();  
}

另一种方法是使用 File 类,它有一些方便的方法,比如ReadLines

string secondLine = File.ReadLines("SourceSettings.txt").ElementAtOrDefault(1);

由于ReadLines也使用了流,因此整个文件不必首先加载到内存中以进行处理。Enumerable.ElementAtOrDefault将只获取第二行并且不会处理更多的行。如果少于两行,则结果为null


完全忘记了这个方法。 - Artiom
@TimSchmelter 它允许在读取文件时写入吗? - Vishal Nair
@VishalNair:不,但你可以使用这个解决方法:https://dev59.com/BG435IYBdhLWcg3wkBBe#5338488 - Tim Schmelter

7

更新 我建议使用Tim Schmelter的解决方案

当您调用ReadLine时,它会将光标移动到下一行。因此,在第二次调用时,您将读取第二行。

string Location;
using(var reader = new StreamReader("SourceSettings.txt"))
{
    Location = reader.ReadLine(); // this call will move caret to the begining of 2nd line.
    Text = reader.ReadLine(); //this call will read 2nd line from the file
}
ofd.InitialDirectory = Location;

不要忘记 使用

或者,如果您只需要从文件中获取一行,则可以通过 File 类的 ReadLines。但是,使用 ElementAtOrDefault 的解决方案是最好的选择,正如 Tim Schmelter 所指出的那样。

var Text = File.ReadLines(@"C:\Projects\info.txt").Skip(1).First()

ReadLines和ReadAllLines方法的区别如下:使用ReadLines时,您可以在整个字符串集合返回之前开始枚举字符串集合;而使用ReadAllLines时,必须等待整个字符串数组返回后才能访问该数组。因此,当您处理非常大的文件时,ReadLines可能更加高效。因此,与ReadAllLines相比,它不会将所有行读入内存中。

嗯...但是Skip会返回什么呢?它会强制完整枚举以便确定第一行之后的所有行吗?我猜它会这样做,所以你最终仍然需要读取整个文件。 - musefan
Skip 返回一个新的 IEnumerable,它将跳过第一个元素。除非你像这样做:File.ReadLines(@"C:\Projects\info.txt").Skip(1).ToArray(),否则它不会强制读取文件中的所有行。来自 MSDN:即时返回值是一个对象,它存储执行操作所需的所有信息。 - Artiom
是的,那很有道理。 - musefan

3
这行代码可以使用Linq进行读取,如下所示。
var SecondLine = File.ReadAllLines("SourceSettings.txt").Skip(1).FirstOrDefault();

我觉得这个踩票令人惊讶。是因为需要阅读整个文件吗? - Codor
和我一样) 不知道为什么会被踩,因为它是有效的。 - Artiom
是的,按你所预期的,downvote 是因为读取整个文件。OP 只想要第二行,而你建议读取所有行?可能是一个五千万行的文件 :/ 然后添加 Skip 可能会更糟糕,因为我认为它会复制整个数组,除了第一行。这只是一个对于如此简单的事情的不良建议。 - musefan
2
@musefan:即使ElementAtOrdefault更合适,那个假设也是不正确的。Skip不会复制任何东西,因为它使用了延迟执行。但当然,在这里使用File.ReadLines要好得多。 - Tim Schmelter
@TimSchmelter 感谢您提供 ElementAtOrDefault 这个我之前不知道的方法。 - Codor
1
@TimSchmelter:是的,Artion告诉了我,因为我显然没有心情自己检查这些东西。所以“Skip”不是问题。但是,这是糟糕的代码,特别是如果你已经知道它为什么糟糕(你可能会原谅没有意识到这个问题)。我不知道为什么有两个人点赞它。仅仅因为某些东西能够工作,并不意味着它是好的。 - musefan

2
private string GetLine(string filePath, int line)
{
    using (var sr = new StreamReader(filePath))
    {
        for (int i = 1; i < line; i++)
             sr.ReadLine();
        return sr.ReadLine();
     }
 }

希望这能帮到你 :)

这实际上是一个有用的函数,不确定为什么它被踩了,我的意思是,作为一个独立的函数,你可能想在其中加入验证检查,但作为一个概念,我认为这是一个好答案。 - musefan
这个方法很有用,但在框架中已经可用:File.ReadLines(path).ElementAtOrDefault(line)。上述方法即使已经返回了 null,因为它已经到达流的末尾,仍然会继续调用 ReadLine - Tim Schmelter

-1

如果您知道您的第二行是唯一的,因为它包含一个特定关键词,在文件中没有其他地方出现,那么您也可以使用linq,好处是“第二”行在将来可以是任何行。

             var myLine = File.ReadLines("SourceSettings.txt")
            .Where(line => line.Contains("The Keyword"))
            .ToList();

OP没有提到要搜索关键词。只是一个有关获取第二行的简单问题……而且“在未来”关键词可能不再唯一,因此在这种情况下试图考虑假设是没有意义的。 - musefan
是的,但他在谈论一种设置文件,我认为它可能会随着时间的推移而增长或改变,为什么不在您的代码中添加一些灵活性呢? - Bgl86
1
但是你在做一些未被询问的假设。你不知道是否有关键字,所以答案没有帮助。如果您想澄清某些事情或提出建议,应该进行评论。这不是一个只是提供“可能相关”的答案的地方。您应该直接回答每个问题。 - musefan

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