Подтвердить что ты не робот

Наблюдатель файловой системы и большие файлы

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);
}

это не удается с большими файлами, потому что процесс не завершен записью файла. Файл копируется через сеть, поэтому я не знаю размер файла. Какая синхронизация необходима, чтобы сделать это надежным?

4b9b3361

Ответ 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), если это возможно. Это должно дать вам время, необходимое компьютеру для завершения записи файла.

Конечно, для медленных жестких дисков это может быть или может быть достаточно.