Наблюдатель файловой системы и большие файлы
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);
}
это не удается с большими файлами, потому что процесс не завершен записью файла. Файл копируется через сеть, поэтому я не знаю размер файла. Какая синхронизация необходима, чтобы сделать это надежным?
Ответы
Ответ 1
Решение найдено в 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);
}
Ответ 2
Используйте DelayedFileSystemWatcher.cs
Класс http://blogs.msdn.com/b/ahamza/archive/2006/02/06/526222.aspx
а затем этот код.
Проверьте обработчик событий PrintFileSystemEventHandler
. Он пытается прочитать файл в файловом потоке, и если какой-либо ioerror giventhe предполагает, что файл все еще читает, поэтому он ждет интервал (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);
}
У меня нет ссылки на проект. но это поможет.
Ответ 3
Я поддерживаю решение, принятое Шаем Эрлихменом.
Но, как бы то ни было
a) Вы можете не открывать файл с режимом доступа FileAccess.Read, вывести его только для чтения файл
b) Некоторые программы во время загрузки, файл будет иметь какое-то смешное расширение, и когда оно будет завершено, расширение изменится, и хотя файл будет завершен, у вас будет исключение файла, не найденное.
Так обрабатывайте исключения, а также подписывайтесь на file.renamed event
Ответ 4
AFAIK вы не получите уведомление после завершения копирования, вы можете реализовать механизм повтора.
Если вы получаете нарушение сдвига, просто запускайте таймер, чтобы повторить операцию за X секунд.
Вторая повторная попытка должна быть после X * 2 секунд и так далее (с некоторым ограничением, конечно).
Ответ 5
Просто в fswCreated
, спать около 1/2 секунды с Thread.Sleep(500)
, если это возможно. Это должно дать вам время, необходимое компьютеру для завершения записи файла.
Конечно, для медленных жестких дисков это может быть или может быть достаточно.