0

I want to read a text file from last line because it could be big size and just want to check today's log content.

I'm using File.ReadLines() and success to read last line. How can I read the previous line? Or is there any way to get the current line number so that I can subtract the number?

foreach (string f in Directory.GetFiles(sDir, "*.log", SearchOption.AllDirectories))
{
    string last = File.ReadLines(f, Encoding.Default).Last(); //read Last Line here

    if (last.IndexOf("error", StringComparison.OrdinalIgnoreCase) > 0)
    {
        WriteError(last);
    }
}
John Saunders
  • 160,644
  • 26
  • 247
  • 397
Elena
  • 3
  • 1
  • 3
  • 1
    Just one line? How will you know for sure how far back to go? If you'll decide somehow on the fly, you're probably better off starting over using streams, where you can move the read pointer backwards. – Joel Coehoorn Dec 02 '14 at 03:38

2 Answers2

0
foreach (string f in Directory.GetFiles(sDir, "*.log", SearchOption.AllDirectories))
{
    string last="", prev="";
    foreach (string cur in  File.ReadLines(f, Encoding.Default) )
    {
        prev = last;
        last = cur;
    }

    //not sure what you want to do with "prev" here.
    if (last.IndexOf("error", StringComparison.OrdinalIgnoreCase) > 0)
    {
        WriteError(last);
    }
}
Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
  • I strongly suspect OP is looking for more than just last+next to last, and in this case it does not scale... – Alexei Levenkov Dec 02 '14 at 03:35
  • It's not that hard to add an array for the desired number of lines and just shift the array, but until the OP adds more info we have no way to know how much of that to do. I don't see how to provide any more than this until the question is updated. – Joel Coehoorn Dec 02 '14 at 03:38
0

It's not really clear to me whether you are asking to avoid reading the whole file (in which case the duplicate answer proposed is the best way to approach this), or you just want to be able to figure out the next-to-the-last line in the file.

If the latter, then this would work:

string[] Tail(string file, int maxLinesToReturn, Encoding encoding)
{
    Queue<string> mostRecentLines = new Queue<string>();

    foreach (string line in File.ReadLines(file, encoding))
    {
        if (mostRecentLines.Count >= maxLinesToReturn)
        {
            mostRecentLines.Dequeue();
        }
        mostRecentLines.Enqueue(line);
    }

    return mostRecentLines.ToArray();
}

Use like this:

foreach (string f in Directory.GetFiles(sDir, "*.log", SearchOption.AllDirectories))
{
    foreach (string line in Tail(f, 2, Encoding.Default)
        .Where(line => line.IndexOf("error", StringComparison.OrdinalIgnoreCase) > 0)))
    {
        WriteError(line);
    }
}
Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
  • Both our answers still read the whole file. That's how they know where the line breaks are. If he wants to avoid reading the whole file, he'll need to work at a much lower level, using streams to work his way backwards from the end. – Joel Coehoorn Dec 02 '14 at 05:17
  • Yup, exactly. That's why I also voted to close the question as a duplicate of the answer referenced in the first comment of the question (which is an implementation that does exactly that, working backwards from the end). But it's an entirely reasonable reading of the question to infer that s/he doesn't mind reading the whole file: even a "huge" file that could potentially generate way more output than a human would want to read could be processed in a relatively short period of time. – Peter Duniho Dec 02 '14 at 05:47