I am trying to add FileSystemWatcher
in Windows Service of my application.In my case i have a textfile which is getting updated continuously with may be one line or more than one line and Every time the file gets updated i need to read all those textfile lines that has not been read before .
I goolged and got to know that this
File.ReadText(@"C:\Filename.txt").Last();
will give me the Last line of the textfile once the file gets updated but i am not sure whether it will give all the unread line or only the last line of the textfile.Also my textfile is getting updated line by line.
In either case what will be the possible solution for this.
If the textfile is getting updated line by line will the FileSystemWatcher
will also see that many times to get the last line added into the file.
Please help me.
Updated Code..
using (var sr = new StreamReader(@"C:\Temp\LineTest.txt"))
{
string line;
long pos = 0;
while ((line = sr.ReadLine()) != null)
{
Console.Write("{0:d3} ", pos);
Console.WriteLine(line);
pos += line.Length;
}
}
Updated Code.
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
}
private System.Threading.Thread _thread;
private ManualResetEvent _shutdownEvent = new ManualResetEvent(false);
int lineCount;
long previousLength = 0;
string filepath = "C:\\Temp\\LineTest.txt";
public void OnDebug()
{
OnStart(null);
}
protected override void OnStart(string[] args)
{
_thread = new Thread(addLogic);
_thread.Start();
}
//This event is raised when a file is changed
private void Watcher_Changed(object sender, FileSystemEventArgs e)
{
_thread = new Thread(addlogic);
_thread.Start();
}
public static string[] ReadFromFile(string filePath, int count, ref int lineCount)
{
lineCount += count;
return File.ReadLines(filePath).Skip(lineCount).Take(count).ToArray();
}
public void addlogic()
{
//Add Logic Here
//How to use lineCount here to read specific line that i am not getting
//If all textfile gets traversed then is FileSystemWatcher
FileSystemWatcher Watcher = new FileSystemWatcher(filepath);
Watcher.EnableRaisingEvents = true;
Watcher.Changed += new FileSystemEventHandler(Watcher_Changed);
}
}
protected override void OnStop()
{
_shutdownEvent.Set();
_thread.Join(); // wait for thread to stop
}
}
}
I just wrote a simple class to read the added lines. This actually reads anything append to the file even in the same line.
public class AddedContentReader
{
private readonly FileStream _fileStream;
private readonly StreamReader _reader;
//Start position is from where to start reading first time. consequent read are managed by the Stream reader
public AddedContentReader(string fileName, long startPosition = 0)
{
//Open the file as FileStream
_fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
_reader = new StreamReader(_fileStream);
//Set the starting position
_fileStream.Position = startPosition;
}
//Get the current offset. You can save this when the application exits and on next reload
//set startPosition to value returned by this method to start reading from that location
public long CurrentOffset
{
get { return _fileStream.Position; }
}
//Returns the lines added after this function was last called
public string GetAddedLines()
{
return _reader.ReadToEnd();
}
}
You can call it like this.
private AddedContentReader _freader;
protected override void OnStart(string[] args)
{
_freader = new AddedContentReader("E:\\tmp\\test.txt");
//If you have saved the last position when the application did exit then you can use that value here to start from that location like the following
//_freader = new AddedContentReader("E:\\tmp\\test.txt",lastReadPosition);
}
private void Watcher_Changed(object sender, FileSystemEventArgs e)
{
string addedContent= _freader.GetAddedLines();
//you can do whatever you want with the lines
}
Note: I have not tested this with very fast updates.