如何读取文本文件中的指定行?

给定一个文本文件,我将如何去阅读一个任意的行,而不是在文件中的其他东西?

说,我有一个文件test.txt。 我该如何去阅读文件中的第15行?

我看到的所有东西都涉及将整个文本文件存储为一个string数组,然后使用行号的值作为从数组中使用的string的编号…但有一些复杂性:文本文件是巨大的巨大的机器,我正在编写的应用程序不完全是一个顶尖的系统。 速度不是重中之重,但这绝对是一个重大问题。

是否有任何方法读取文本文件的特定行并将结果存储为string?

感谢您的回应:文件是KINDA结构。 它有25行信息,然后是X行的数字,但第25行的第17行的值是X.

但是,那么有一个空白行,它会重复作为文件中的第二个logging, X可以为每个logging有不同的值。

我想要做的是读取并存储前25行作为独立的值,然后将下一个X (通常约250)行存储为一个数组。 然后,我将把它存储在一个SQL数据库中,并重复NEXTlogging,直到我到达第Y条logging(文件中的logging数在第3行)

编辑2 :好吧,我想我已经得到了一个解决scheme,基于你所有的答案的组合。

我将读取前25行,并将其存储为数组。 我将数组的相关内容复制到局部variables,然后删除前25行。 然后,我可以使用info将下一个X行(数组13中的值)存储为一个数组,将其序列化,然后将其存储在数据库中,然后删除刚刚读取的行。

然后,我可以重复每个后续logging的过程。

当然,这依赖于我所做的一个假设,说实话,我不确定是否属实。 是否有可能从C#中的文本文件中删除前n行,而不必读取整个事情,并重写它没有前n行?

.NET 4.0编辑

从.NET 4.0开始,可以直接访问一行文件。 例如,要访问第15行:

 string line = File.ReadLines(FileName).Skip(14).Take(1).First(); 

这将只返回所需的行


既然你不能预测文件中第i行的位置(你能吗?),你也必须阅读所有以前的行。 如果行号很小,这可能比ReadAllLines方法更有效。

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

如果每一行都是固定的长度,那么你可以在它周围打开一个stream,寻找(每行的字节数)* n到文件中并从那里读取你的行。

 using( Stream stream = File.Open(fileName, FileMode.Open) ) { stream.Seek(bytesPerLine * (myLine - 1), SeekOrigin.Begin); using( StreamReader reader = new StreamReader(stream) ) { string line = reader.ReadLine(); } } 

或者,您可以使用StreamReader读取行,直到find所需的行。 这种方式较慢,但相对于阅读每一行仍然是一个改进。

 using( Stream stream = File.Open(fileName, FileMode.Open) ) { using( StreamReader reader = new StreamReader(fileStream) ) { string line = null; for( int i = 0; i < myLineNumber; ++i ) { line = reader.ReadLine(); } } } 

不幸的是没有。 在原始级别文件不能在行号的基础上工作。 相反,他们在一个位置/抵消的基础上工作。 根文件系统没有行的概念。 这是一个由更高级别组件添加的概念。

所以没有办法告诉操作系统,请在线路上打开文件。 相反,您必须打开文件并跳过计算新行,直到您通过指定的编号。 然后将下一组字节存储到一个数组中,直到find下一个新行。

除非你有固定大小的行,否则你需要阅读每一行,直到你到达你想要的行。 虽然,你不需要存储每一行​​,如果不是你想要的行,就放弃它。

编辑:

如前所述,如果行长是可预测的,也可以在文件中查找 – 也就是说,您可以应用某些确定性函数将行号转换为文件位置。

正如Mehrdad所说,你不能只读取第n行而不读取文件。 但是,您不需要将整个文件存储在内存中,只需放弃不需要的数据即可。

 string line; using (StreamReader sr = new StreamReader(path)) for (int i = 0; i<15; i++) { line = sr.ReadLine(); if (line==null) break; // there are less than 15 lines in the file } 

每次读五条线,只要把你的陈述放在if语句中,就是这样

  String str1 = @"C:\Users\TEMP\Desktop\StaN.txt"; System.IO.StreamReader file = new System.IO.StreamReader(str1); line = file.ReadLine(); Int32 ctn=0; try { while ((line = file.ReadLine()) != null) { if (Counter == ctn) { MessageBox.Show("I am here"); ctn=ctn+5; continue; } else { Counter++; //MessageBox.Show(Counter.ToString()); MessageBox.Show(line.ToString()); } } file.Close(); } catch (Exception er) { } 

如果这些行的长度都是固定的,则可以使用stream的Seek方法移动到正确的起始位置。

如果这些线条的长度可变,那么您的选项会受到更多的限制。

如果这是一个文件,你将只使用一次,然后丢弃,那么你最好阅读它,并在memeory与它一起工作。

如果这是一个您将要保留的文件,并且将从不止写入的文件读取,您可以创build一个包含每行起始位置的自定义索引文件。 然后使用该索引来获取您的Seek位置。 创build索引文件的过程是资源密集型的。 每当你添加一个新的行到文件,你将需要更新索引,所以维护成为一个不平凡的问题。

你可以一行一行阅读,所以你不必一次读完全部(可能根本就不用)

 int i=0 while(!stream.eof() && i!=lineNum) stream.readLine() i++ line = stream.readLine() 

如果您的文件包含不同长度的行,并且您需要经常读取行,并且需要快速读取,则可以通过读取一次文件索引来保存每个新行的位置,然后在需要读取行时,你只要在你的索引中查找该行的位置,在那里寻找,然后阅读该行。

如果你添加新行到文件中,你可以添加新行索引,而不需要重新索引。 尽pipe如果你的文件改变了你已经索引的行,那么你必须重新索引。

虽然在不读取文件中的数据的情况下,不能直接在非对称文件中查找第N行(因为您需要统计已经进入文件的行数),您可以计算换行符,直到到达你需要哪一行占用最less的内存,可能是最好的性能。

这比将所有内容读入数组要更有效率,因为它只会读入文件,直到到达文件末尾或行号(以先到者为准)。 这远非完美,但可能会适合您的需求:

 string line15 = ReadLine(@"C:\File.csv", 15); public string ReadLine(string FilePath, int LineNumber){ string result = ""; try{ if( File.Exists(FilePath) ){ using (StreamReader _StreamReader = new StreamReader(FilePath)){ for (int a = 0; a < LineNumber; a++) { result = _StreamReader.ReadLine(); } } } }catch{} return result; } 
  if (File.Exists(fpath)) { var data = File.ReadLines(fpath); Console.WriteLine(data.ToArray()[14]); } 

尝试和testing。 这很简单,如下所示:

 string line = File.ReadLines(filePath).ElementAt(actualLineNumber - 1); 

只要你有一个文本文件,这应该工作。 稍后,根据您希望读取的数据,您可以相应地投射string并使用它。

晚回答,但值得。

您需要加载数组或列表对象中的行,其中每行将被分配给一个索引,然后只需在for循环中通过其索引调用任何范围的行。

解决scheme是相当不错的,但之间有一个内存消耗。

给它尝试…它的价值