在项目中需要用FileSystemWatcher对单个文件内容进行监视,文件中每添加一行则需要Fire相应的事件,代码如下
public class CommandWatcher
{
public event EventHandler<CommandEventArgs> CommandHandler;
Fields Fields
public CommandWatcher(string cmdfile)
{
this.fileName = cmdfile;
isChangeImmediate = true;
}
//
// Summary:
// Raises the System.IO.FileSystemWatcher.Changed event.
//
// Parameters:
// e:
// A System.IO.FileSystemEventArgs that contains the event data.
protected void OnChanged(object sender, FileSystemEventArgs e)
{
ReloadFile();
}
//
// Summary:
// Raises the System.IO.FileSystemWatcher.Error event.
//
// Parameters:
// e:
// An System.IO.ErrorEventArgs that contains the event data.
protected void OnError(object sender, ErrorEventArgs e)
{
}
//
// Summary:
// Raises the System.IO.FileSystemWatcher.Renamed event.
//
// Parameters:
// e:
// A System.IO.RenamedEventArgs that contains the event data.
protected void OnRenamed(object sender, RenamedEventArgs e)
{
}
/// <summary>
/// Hook up for the currently selected monitoring method.
/// </summary>
public void Start()
{
if (isChangeImmediate)
{
// stop timer if running
ClearTimer();
// If a file is set and the watcher has not been set up yet then create it
if (null != fileName && null == watcher)
{
string path = Path.GetDirectoryName(fileName);
string baseName = Path.GetFileName(fileName);
// Use the FileSystemWatcher class to detect changes to the log file immediately
// We must watch for Changed, Created, Deleted, and Renamed events to cover all cases
watcher = new System.IO.FileSystemWatcher(path, baseName);
FileSystemEventHandler handler = new FileSystemEventHandler(OnChanged);
watcher.Changed += handler;
watcher.Created += handler;
watcher.Deleted += handler;
watcher.Renamed += OnRenamed;
// Without setting EnableRaisingEvents nothing happens
watcher.EnableRaisingEvents = true;
}
}
else
{
// On a timer so clear the watcher if previously set up
ClearWatcher();
int numSeconds = 5;
if (null != timer)
{
// Timer is already running so just make sure the interval is correct
if (timer.Interval != 1000 * numSeconds)
{
timer.Interval = 1000 * numSeconds;
}
}
else
{
// Fire up a timer if the user entered a valid time interval
if (0 != numSeconds)
{
timer = new System.Windows.Forms.Timer();
timer.Interval = 1000 * numSeconds;
timer.Tick += timerTick;
timer.Start();
}
}
}
this.ReloadFile();
}
void timerTick(object sender, EventArgs e)
{
UpdateBasedOnFileTime();
}
/// <summary>
/// Update the log file if the modified timestamp has changed since the last time the file was read.
/// </summary>
private void UpdateBasedOnFileTime()
{
if (null != fileName)
{
// This returns "12:00 midnight, January 1, 1601 A.D." if the file does not exist
DateTime newLastModifiedTime = File.GetLastWriteTime(fileName);
if ((newLastModifiedTime.Year < 1620 && newLastModifiedTime != lastModifiedTime)
|| newLastModifiedTime > lastModifiedTime)
{
//OnLogFileChanged();
ReloadFile();
}
}
}
/// <summary>
/// Read the log file.
/// </summary>
/// <remarks>If the user has some text selected then keep that text selected.</remarks>
private void ReloadFile()
{
if (reloadingFile) return; // already busy doing this
reloadingFile = true;
try
{
if (null == fileName)
{
// textBoxContents.Text = "";
}
else
{
string newFileLines = "";
lastModifiedTime = File.GetLastWriteTime(fileName); // Remember when we last read in this file
long newLength = 0; // will be set properly later if all is well
bool fileExists = File.Exists(fileName);
bool needToClear = !fileExists;
if (fileExists)
{
// It is possible the file will be in use when we read it (especially if using Immediate mode)
// So, we will try up to 5 times to access the file
int count = 0;
bool success = false;
while (count < 5 && !success)
{
try
{
// Open with the least amount of locking possible
using (FileStream stream = File.Open(fileName, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
{
newLength = stream.Length;
if (newLength >= lastFileSize)
{
stream.Position = lastFileSize; // Only read in new lines added
}
else
{
needToClear = true;
}
using (StreamReader reader = new StreamReader(stream))
{
newFileLines = reader.ReadToEnd();
if (newFileLines != string.Empty)
{
if (this.CommandHandler != null)
this.CommandHandler(this, new CommandEventArgs(newFileLines));
}
//string []tmp = newFileLines.Split(seprater, StringSplitOptions.RemoveEmptyEntries);
}
}
success = true;
}
catch (IOException)
{
System.Threading.Thread.Sleep(50); // Give a little while to free up file
}
++count;
}
}
// Remember the current file length so we can read only newly added log lines the next time the log file is read
lastFileSize = newLength;
if(lastFileSize > 1024 * 1024 * 2)
{
File.Delete(fileName);
File.Create(fileName);
}
if (0 != newFileLines.Length)
{
// See if this log file has proper cr/lf and if not convert
int lastCr = newFileLines.LastIndexOf('\n');
if (-1 != lastCr && 0 < lastCr)
{
if (newFileLines[lastCr - 1] != '\r')
{
// OK, this file only has Cr and we need to convert to CrLf
newFileLines = newFileLines.Replace("\n", "\r\n");
}
}
}
}
}
finally
{
// Put clearing this flag in a finally so we know it will be cleared
reloadingFile = false;
}
}
/// <summary>
/// Cleanup the <see cref="Timer"/>
/// </summary>
private void ClearTimer()
{
if (null != timer)
{
timer.Tick -= timerTick;
timer.Dispose();
timer = null;
}
}
/// <summary>
/// Cleanup the <see cref="FileSystemWatcher"/>
/// </summary>
private void ClearWatcher()
{
if (null != watcher)
{
FileSystemEventHandler handler = new FileSystemEventHandler(OnChanged);
watcher.Changed -= handler;
watcher.Created -= handler;
watcher.Deleted -= handler;
watcher.Renamed -= OnRenamed;
watcher.Dispose();
watcher = null;
}
}
}
{
public event EventHandler<CommandEventArgs> CommandHandler;
Fields Fields
public CommandWatcher(string cmdfile)
{
this.fileName = cmdfile;
isChangeImmediate = true;
}
//
// Summary:
// Raises the System.IO.FileSystemWatcher.Changed event.
//
// Parameters:
// e:
// A System.IO.FileSystemEventArgs that contains the event data.
protected void OnChanged(object sender, FileSystemEventArgs e)
{
ReloadFile();
}
//
// Summary:
// Raises the System.IO.FileSystemWatcher.Error event.
//
// Parameters:
// e:
// An System.IO.ErrorEventArgs that contains the event data.
protected void OnError(object sender, ErrorEventArgs e)
{
}
//
// Summary:
// Raises the System.IO.FileSystemWatcher.Renamed event.
//
// Parameters:
// e:
// A System.IO.RenamedEventArgs that contains the event data.
protected void OnRenamed(object sender, RenamedEventArgs e)
{
}
/// <summary>
/// Hook up for the currently selected monitoring method.
/// </summary>
public void Start()
{
if (isChangeImmediate)
{
// stop timer if running
ClearTimer();
// If a file is set and the watcher has not been set up yet then create it
if (null != fileName && null == watcher)
{
string path = Path.GetDirectoryName(fileName);
string baseName = Path.GetFileName(fileName);
// Use the FileSystemWatcher class to detect changes to the log file immediately
// We must watch for Changed, Created, Deleted, and Renamed events to cover all cases
watcher = new System.IO.FileSystemWatcher(path, baseName);
FileSystemEventHandler handler = new FileSystemEventHandler(OnChanged);
watcher.Changed += handler;
watcher.Created += handler;
watcher.Deleted += handler;
watcher.Renamed += OnRenamed;
// Without setting EnableRaisingEvents nothing happens
watcher.EnableRaisingEvents = true;
}
}
else
{
// On a timer so clear the watcher if previously set up
ClearWatcher();
int numSeconds = 5;
if (null != timer)
{
// Timer is already running so just make sure the interval is correct
if (timer.Interval != 1000 * numSeconds)
{
timer.Interval = 1000 * numSeconds;
}
}
else
{
// Fire up a timer if the user entered a valid time interval
if (0 != numSeconds)
{
timer = new System.Windows.Forms.Timer();
timer.Interval = 1000 * numSeconds;
timer.Tick += timerTick;
timer.Start();
}
}
}
this.ReloadFile();
}
void timerTick(object sender, EventArgs e)
{
UpdateBasedOnFileTime();
}
/// <summary>
/// Update the log file if the modified timestamp has changed since the last time the file was read.
/// </summary>
private void UpdateBasedOnFileTime()
{
if (null != fileName)
{
// This returns "12:00 midnight, January 1, 1601 A.D." if the file does not exist
DateTime newLastModifiedTime = File.GetLastWriteTime(fileName);
if ((newLastModifiedTime.Year < 1620 && newLastModifiedTime != lastModifiedTime)
|| newLastModifiedTime > lastModifiedTime)
{
//OnLogFileChanged();
ReloadFile();
}
}
}
/// <summary>
/// Read the log file.
/// </summary>
/// <remarks>If the user has some text selected then keep that text selected.</remarks>
private void ReloadFile()
{
if (reloadingFile) return; // already busy doing this
reloadingFile = true;
try
{
if (null == fileName)
{
// textBoxContents.Text = "";
}
else
{
string newFileLines = "";
lastModifiedTime = File.GetLastWriteTime(fileName); // Remember when we last read in this file
long newLength = 0; // will be set properly later if all is well
bool fileExists = File.Exists(fileName);
bool needToClear = !fileExists;
if (fileExists)
{
// It is possible the file will be in use when we read it (especially if using Immediate mode)
// So, we will try up to 5 times to access the file
int count = 0;
bool success = false;
while (count < 5 && !success)
{
try
{
// Open with the least amount of locking possible
using (FileStream stream = File.Open(fileName, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
{
newLength = stream.Length;
if (newLength >= lastFileSize)
{
stream.Position = lastFileSize; // Only read in new lines added
}
else
{
needToClear = true;
}
using (StreamReader reader = new StreamReader(stream))
{
newFileLines = reader.ReadToEnd();
if (newFileLines != string.Empty)
{
if (this.CommandHandler != null)
this.CommandHandler(this, new CommandEventArgs(newFileLines));
}
//string []tmp = newFileLines.Split(seprater, StringSplitOptions.RemoveEmptyEntries);
}
}
success = true;
}
catch (IOException)
{
System.Threading.Thread.Sleep(50); // Give a little while to free up file
}
++count;
}
}
// Remember the current file length so we can read only newly added log lines the next time the log file is read
lastFileSize = newLength;
if(lastFileSize > 1024 * 1024 * 2)
{
File.Delete(fileName);
File.Create(fileName);
}
if (0 != newFileLines.Length)
{
// See if this log file has proper cr/lf and if not convert
int lastCr = newFileLines.LastIndexOf('\n');
if (-1 != lastCr && 0 < lastCr)
{
if (newFileLines[lastCr - 1] != '\r')
{
// OK, this file only has Cr and we need to convert to CrLf
newFileLines = newFileLines.Replace("\n", "\r\n");
}
}
}
}
}
finally
{
// Put clearing this flag in a finally so we know it will be cleared
reloadingFile = false;
}
}
/// <summary>
/// Cleanup the <see cref="Timer"/>
/// </summary>
private void ClearTimer()
{
if (null != timer)
{
timer.Tick -= timerTick;
timer.Dispose();
timer = null;
}
}
/// <summary>
/// Cleanup the <see cref="FileSystemWatcher"/>
/// </summary>
private void ClearWatcher()
{
if (null != watcher)
{
FileSystemEventHandler handler = new FileSystemEventHandler(OnChanged);
watcher.Changed -= handler;
watcher.Created -= handler;
watcher.Deleted -= handler;
watcher.Renamed -= OnRenamed;
watcher.Dispose();
watcher = null;
}
}
}