[英]Filesystem watcher and large files
var fsw = new FileSystemWatcher(sPath, "*.PPF");
fsw.NotifyFilter = NotifyFilters.FileName;
fsw.IncludeSubdirectories = true;
fsw.Created += FswCreated;
fsw.EnableRaisingEvents = true;
static void FswCreated(object sender, FileSystemEventArgs e)
{
string sFile = e.FullPath;
string[] arrLines = File.ReadAllLines(sFile);
}
這對於大文件失敗,因為編寫文件時沒有完成該過程。 該文件是通過網絡復制的,所以我不知道文件的大小。 需要什么樣的同步才能使其穩健?
在stackoverflow上找到解決方案並對其進行了一些修改。
static bool IsFileLocked(FileInfo file)
{
FileStream stream = null;
try
{
stream = file.Open(FileMode.Open,
FileAccess.ReadWrite, FileShare.None);
}
catch (IOException)
{
//the file is unavailable because it is:
//still being written to
//or being processed by another thread
//or does not exist (has already been processed)
return true;
}
finally
{
if (stream != null)
stream.Close();
}
//file is not locked
return false;
}
static void FswCreated(object sender, FileSystemEventArgs e)
{
string sFile = e.FullPath;
Console.WriteLine("processing file : " + sFile);
// Wait if file is still open
FileInfo fileInfo = new FileInfo(sFile);
while(IsFileLocked(fileInfo))
{
Thread.Sleep(500);
}
string[] arrLines = File.ReadAllLines(sFile);
}
使用DelayedFileSystemWatcher.cs
類http://blogs.msdn.com/b/ahamza/archive/2006/02/06/526222.aspx
然后這段代碼。 檢查PrintFileSystemEventHandler
事件處理程序。 它嘗試在文件流中讀取文件,如果有任何錯誤,則假定文件仍在讀取,因此它等待一段時間(本例中為2秒),然后再次嘗試。 檢查CONVERSION:
標簽
static void Main(string[] args)
{
DelayedFileSystemWatcher dfw = new DelayedFileSystemWatcher(@"C:\\Test", "*.*");
dfw.Changed += new FileSystemEventHandler(Program.FileSystemEventHandlerMethod);
dfw.Created += new FileSystemEventHandler(Program.FileSystemEventHandlerMethod);
dfw.Deleted += new FileSystemEventHandler(Program.FileSystemEventHandlerMethod);
dfw.Error += new ErrorEventHandler(Program.ErrorEventHandlerMethod);
dfw.Renamed += new RenamedEventHandler(Program.RenamedEventHandlerMethod);
dfw.IncludeSubdirectories = true;
dfw.ConsolidationInterval = 1000;
dfw.EnableRaisingEvents = true;
Console.WriteLine("Press \'q\' to quit the sample.");
while (Console.Read() != 'q') ;
//System.Threading.Thread.Sleep(60000);
dfw.Dispose();
}
private static void FileSystemEventHandlerMethod(object sender, FileSystemEventArgs e)
{
PrintFileSystemEventHandler(e);
System.Console.WriteLine();
}
private static void ErrorEventHandlerMethod(object sender, ErrorEventArgs e)
{
System.Console.WriteLine(e.GetException().Message);
System.Console.WriteLine();
}
private static void RenamedEventHandlerMethod(object sender, RenamedEventArgs e)
{
PrintRenamedEventHandler(e);
System.Console.WriteLine();
}
private static void PrintFileSystemEventHandler(FileSystemEventArgs e)
{
CONVERSION:
try
{
if (e.ChangeType != WatcherChangeTypes.Deleted)
{
if (!isFolder(e.FullPath) && isFile(e.FullPath))
{
FileStream fs = new FileStream(e.FullPath, FileMode.Open, FileAccess.Read, FileShare.None);
fs.Close();
}
}
System.Console.WriteLine(e.Name + " " + e.FullPath + " " + e.ChangeType);
}
catch (System.IO.IOException)
{
Console.WriteLine("There was an IOException error or File is still copying. Retrying in 2 seconds...");
System.Threading.Thread.Sleep(2000);
goto CONVERSION;
}
//System.Console.WriteLine(e.Name);
//System.Console.WriteLine(e.FullPath);
//System.Console.WriteLine(e.ChangeType);
}
private static bool isFolder(string strPath)
{
bool isFolderExist = false;
try
{
isFolderExist = Directory.Exists(strPath);
}
catch
{
isFolderExist = false;
}
return isFolderExist;
}
private static bool isFile(string strPath)
{
bool isFileExist = false;
try
{
isFileExist = File.Exists(strPath);
}
catch
{
isFileExist = false;
}
return isFileExist;
}
private static void PrintRenamedEventHandler(RenamedEventArgs e)
{
PrintFileSystemEventHandler(e);
System.Console.WriteLine(e.OldName);
System.Console.WriteLine(e.OldFullPath);
}
我沒有項目的鏈接。 但是這會有所幫助。
我支持Shay Erlichmen接受的解決方案。 但是,a)你可能不想打開文件訪問模式FileAccess.Read,包括它的只讀文件
b)一些程序在下載時,文件將有一些有趣的擴展,完成后,擴展名將會改變,雖然文件已經完成,但你將找不到文件異常。
因此處理異常,並訂閱file.renamed事件
完成復制后,您不會收到AFAIK通知,您可以實施重試機制。
如果您遇到剪切違規,只需觸發計時器即可在X秒內重試該操作。
第二次重試應該在X * 2秒之后,依此類推(當然有一些限制)。
只需在你的fswCreated
,如果可能的話,使用Thread.Sleep(500)
睡眠約1/2秒。 這應該給你計算機完成文件編寫所需的時間。
當然,對於較慢的硬盤驅動器,這可能或可能有足夠的時間。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.