1

I need some assistance, I am writing a method to read a text file, and if any exception occurs I append a line to the text file. e.g "**"

So what I need to know is how can I check for that specific line of text in the text file without reading every line of the text file, like a peek method or something.

Any help would be appreciated.

Thanks in advance.

johnnie
  • 1,837
  • 5
  • 23
  • 36
  • if the file is moderately small, there is no reason to not load it into memory. Your computer can most probably handle a few MB of data in cache memory – default Apr 17 '12 at 08:55
  • Are you talking about checking for that specific line of text at some later point after you've processed the file initially? – Nick Apr 17 '12 at 08:56
  • 1
    @johnnie - Why would you want to do that ? Usually when you're reading a file you would typically leave the file you're reading untouched – abhilash Apr 17 '12 at 08:57
  • have a look at http://stackoverflow.com/questions/4619735/how-to-read-last-n-lines-of-log-file – Ali Apr 17 '12 at 08:58
  • @ABKolan: that's quite an assumption! – Nick Apr 17 '12 at 08:59

4 Answers4

2

You can use File.ReadLines in combination with Any:

bool isExcFile = System.IO.File.ReadLines(path).Any(l => l == "**");

The ReadLines and ReadAllLines methods differ as follows: When you use ReadLines, you can start enumerating the collection of strings before the whole collection is returned; when you use ReadAllLines, you must wait for the whole array of strings be returned before you can access the array. Therefore, when you are working with very large files, ReadLines can be more efficient.

Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
1

I have found a solution, the line I have appended to the file will always be the last line in the file, so I created a method to read the last line. See below:

public string ReadLastLine(string path)
        {
            string returnValue = "";
            FileStream fs = new FileStream(path, FileMode.Open);
            for (long pos = fs.Length - 2; pos > 0; --pos)
            {
                fs.Seek(pos, SeekOrigin.Begin);               
                StreamReader ts = new StreamReader(fs);
                returnValue = ts.ReadToEnd();
                int eol = returnValue .IndexOf("\n");
                if (eol >= 0)
                {                    
                    fs.Close();
                    return returnValue .Substring(eol + 1);
                }                
            }
            fs.Close();
            return returnValue ;
        }
johnnie
  • 1,837
  • 5
  • 23
  • 36
0

You will need to maintain a separate file with indexes (such as comma delimited) of where your special markers are. Then you can only read those indexes and use the Seek method to jump to that point in the filestream.

If your file is relatively small, let's say <50MB this is an overkill. More than that you can consider maintaining the index file. You basically have to weigh the performance of an extra IO call (that is reading the index file) with that of simply reading from the filestream each line.

Candide
  • 30,469
  • 8
  • 53
  • 60
0

From what I understand you want to process some files and after the processing find out which files contain the "**" symbol, without reading every line of the file.

If you append the "**" to the end of the file you could do something like:

using (StreamReader sr = new StreamReader(File.OpenText(fileName)))
{
    sr.BaseStream.Seek(-3, SeekOrigin.End);
    string endToken = sr.ReadToEnd();
    if (endToken == "**\n")
    {
        // if needed, go back to start of file:
        sr.BaseStream.Seek(0, SeekOrigin.Begin);
            // do something with the file
    }
}