22

我有一个程序,它读取一个文本文件并将其处理为分成多个部分。

所以问题是如何更改程序以允许程序在使用 Stream Reader 读取文件时跳过读取文件的前 5 行?

有人可以就代码提供建议吗?谢谢!

代码:

class Program
{
    static void Main(string[] args)
    {
        TextReader tr = new StreamReader(@"C:\Test\new.txt");

        String SplitBy = "----------------------------------------";

        // Skip first 5 lines of the text file?
        String fullLog = tr.ReadToEnd();

        String[] sections = fullLog.Split(new string[] { SplitBy }, StringSplitOptions.None);

        //String[] lines = sections.Skip(5).ToArray();

        foreach (String r in sections)
        {
            Console.WriteLine(r);
            Console.WriteLine("============================================================");
        }
    }
}
4

6 回答 6

27

尝试以下

// Skip 5 lines
for(var i = 0; i < 5; i++) {
  tr.ReadLine();
}

// Read the rest
string remainingText = tr.ReadToEnd();
于 2010-12-11T18:49:34.020 回答
13

如果线路是固定的,那么最有效的方法如下:

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();
    }
}

如果这些行的长度不同,那么您必须一次读一行,如下所示:

using (var sr = new StreamReader("file"))
{
    for (int i = 1; i <= 5; ++i)
        sr.ReadLine();
}
于 2010-12-11T18:57:12.060 回答
8

如果你想在你的程序中更多地使用它,那么创建一个继承自 StreamReader 的自定义类并能够跳过行可能是个好主意。

这样的事情可以做到:

class SkippableStreamReader : StreamReader
{
    public SkippableStreamReader(string path) : base(path) { }

    public void SkipLines(int linecount)
    {
        for (int i = 0; i < linecount; i++)
        {
            this.ReadLine();
        }
    }
}

在此之后,您可以使用 SkippableStreamReader 的函数来跳过行。例子:

SkippableStreamReader exampleReader = new SkippableStreamReader("file_to_read");

//do stuff
//and when needed
exampleReader.SkipLines(number_of_lines_to_skip);
于 2013-01-31T18:57:40.397 回答
5

我将在列表中添加另外两个建议。

如果总是有一个文件,而你只会阅读,我建议:

var lines = File.ReadLines(@"C:\Test\new.txt").Skip(5).ToArray();

File.ReadLines 不会阻止其他文件,只会将必要的行加载到内存中。

如果您的流可以来自其他来源,那么我建议这种方法:

class Program
{
    static void Main(string[] args)
    {
        //it's up to you to get your stream
        var stream = GetStream();

        //Here is where you'll read your lines. 
        //Any Linq statement can be used here.
        var lines = ReadLines(stream).Skip(5).ToArray();

        //Go on and do whatever you want to do with your lines...
    }
}

public IEnumerable<string> ReadLines(Stream stream)
{
    using (var reader = new StreamReader(stream))
    {
        while (!reader.EndOfStream)
        {
            yield return reader.ReadLine();
        }
    }
}

完成后,Iterator 块将自动清理它。是 Jon Skeet 的一篇文章,深入探讨了它是如何工作的(向下滚动到“最后……”部分)。

于 2014-09-16T17:59:25.070 回答
1

我猜这很简单:

    static void Main(string[] args)
    {
        var tr = new StreamReader(@"C:\new.txt");

        var SplitBy = "----------------------------------------";

        // Skip first 5 lines of the text file?
        foreach (var i in Enumerable.Range(1, 5)) tr.ReadLine();
        var fullLog = tr.ReadToEnd(); 

        String[] sections = fullLog.Split(new string[] { SplitBy }, StringSplitOptions.None);

        //String[] lines = sections.Skip(5).ToArray();

        foreach (String r in sections)
        {
            Console.WriteLine(r);
            Console.WriteLine("============================================================");
        }
    }
于 2010-12-11T19:00:47.757 回答
1

StreamReaderwith ReadLineorReadToEnd实际上会将字节读入内存,即使您不处理这些行,它们也会被加载,这会在大文件(10+ MB)的情况下影响应用程序的性能。

如果要跳过特定数量的行,则需要知道要移动到的文件的位置,这为您提供了两种选择:

  1. 如果您知道行长,您可以计算位置并使用 Stream.Seek 移动到那里。这是在不阅读流内容的情况下跳过流内容的最有效方式。这里的问题是您很少知道行长。
var linesToSkip = 10;
using(var reader = new StreamReader(fileName) )
{
    reader.BaseStream.Seek(lineLength * (linesToSkip - 1), SeekOrigin.Begin);
    var myNextLine = reader.ReadLine();
    // TODO: process the line
}
  1. 如果您不知道行长,则必须逐行阅读并跳过它们,直到找到所需的行号。这里的问题是行号很高,你会受到性能影响
var linesToSkip = 10;
using (var reader = new StreamReader(fileName))
{
    for (int i = 1; i <= linesToSkip; ++i)
        reader.ReadLine();

    var myNextLine = reader.ReadLine();
    // TODO: process the line
}

如果您只需要跳过所有内容,则应该在不将所有内容读入内存的情况下执行此操作:

using(var reader = new StreamReader(fileName) )
{
   reader.BaseStream.Seek(0, SeekOrigin.End);

   // You can wait here for other processes to write into this file and then the ReadLine will provide you with that content

   var myNextLine = reader.ReadLine();
   // TODO: process the line
}
于 2019-03-20T23:13:59.850 回答