Как отследить папку на наличие файлов и переместить указанные файлы в другую папку при работе в фоновом режиме? - PullRequest
0 голосов
/ 22 января 2019

Мне нужна программа, которая будет постоянно отслеживать папку для файлов, когда файл появляется в указанной папке, программа должна подождать, пока файл станет доступным, а затем переместить указанный файл в другую папку.В настоящее время файлы не перемещаются из папки «test» в «test2».

Я сделал так, чтобы при нажатии кнопки «Пуск» форма свернулась и работала в фоновом режиме, постоянно отслеживая папку.

private void btstart_Click(object sender, EventArgs e)
        {
            this.WindowState = FormWindowState.Minimized;

            FileSystemWatcher watcher = new FileSystemWatcher();
            watcher.Path = @"C:\test";
            watcher.NotifyFilter = NotifyFilters.LastWrite;



            watcher.Created += new FileSystemEventHandler(watcher_FileCreated);
            watcher.EnableRaisingEvents = true;
        }

        public static bool Ready(string filename)
        {
            try
            {
                using (FileStream inputStream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.None))
                    return inputStream.Length > 0;
            }
            catch (Exception)
            {
                return false;
            }
        }
        void watcher_FileCreated(object sender, FileSystemEventArgs e)
        {
            string path1 = @"C:\test";
            string path2 = @"C:\test2";
            string files = @"*.*"; 
            string[] fileList = Directory.GetFiles(path1, files);
            foreach (string file in fileList)
            {
                if (Ready(file) == true)
                {
                    File.Move(path1, path2);
                }
            }
        }

По-видимому, это не очевидно, но происходит то, что файл не перемещается из папки «test» в папку «test2», исключение не выдается, ошибок нет, файл не находится виспользовать что-либо, и при этом это не открыто, права доступа также все установлены правильно, файл просто не перемещается

РЕДАКТИРОВАТЬ РЕШЕНИЕ: код работает теперь благодаря ответу, опубликованному в этой теме.Я сам добавил несколько вещей, чтобы обрабатывать дублирующееся исключение.

Переменные folderlocationpath & folderdestinationpath читаются через folderbrowserdialog, так что пользователь сам может выбрать 2 местоположения папки. Это то, что у меня сейчас есть:

string path1 = folderlocationpath;
            string path2 = folderdestinationpath;
            string files = @"*.*";
            string[] fileList = Directory.GetFiles(path1, files);
            foreach (string file in fileList)
            {
                if (Ready(file) == true)
                    try
                    {
                        File.Move(file, Path.Combine(path2, Path.GetFileName(file)));
                    }
                    catch (IOException) // for duplicate files an exception that deletes the file in destination folder and then moves the file from origin folder
                    {
                        string files2 = Path.GetFileName(file);
                        string[] fileList2 = Directory.GetFiles(path2, files2);
                        foreach (string file2 in fileList2)
                            File.Delete(file2);

                        File.Move(file, Path.Combine(path2, Path.GetFileName(file)));
                    }
            }

Ответы [ 2 ]

0 голосов
/ 24 января 2019

Я подумал о том, чтобы написать правку в ответ @BanMe, но кажется, что было бы лучше быть более всеобъемлющим в ответе, так как я бы эффективно добавил дополнительное изменение в его предлагаемое исправление (которое вна самом деле, это очень важно) после собственного тестирования.

Это было проверено и проверено на работу в моей системе.Было одно дополнительное изменение, которое я должен был сделать, чтобы заставить это работать более эффективно.Он включает в себя исправление команды Move, Path.Combine, но, что более важно, добавляет NotifyFilter к FileName.

Вы должны иметь возможность использовать этот раздел своего кода, и он долженработа, как и ожидалось от моего тестирования.

private void btstart_Click(object sender, EventArgs e)
{
    this.WindowState = FormWindowState.Minimized;
    FileSystemWatcher watcher = new FileSystemWatcher();
    watcher.Path = @"C:\test";
    watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName;
    watcher.Created += new FileSystemEventHandler(watcher_FileCreated);
    watcher.EnableRaisingEvents = true;
}

public static bool Ready(string filename)
{
    try
    {
        using (FileStream inputStream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.None))
            return inputStream.Length > 0;
    }
    catch (Exception)
    {
        return false;
    }
}

void watcher_FileCreated(object sender, FileSystemEventArgs e)
{
    string path1 = @"C:\test";
    string path2 = @"C:\test2";
    string files = @"*.*";
    string[] fileList = Directory.GetFiles(path1, files);
    foreach (string file in fileList)
    {
        if (Ready(file) == true)
        {
            File.Move(file, Path.Combine(path2, System.IO.Path.GetFileName(file)));
        }
    }
}

Почему нам нужно расширить NotifyFilters?Взгляните на этот ответ , который я подытожу соответствующей частью здесь:

У меня тоже были проблемы с этим поведением.Если вы пошагово просматриваете код (и если вы посмотрите документацию MSDN, вы обнаружите, что NotifyFilter запускается со значением по умолчанию:

NotifyFilters.FileName | NotifyFilters.DirectoryName | NotifyFilters.LastWrite

Поэтому, когда вы говорите .NotifyFilter = NotifyFilters.CreationTime, вы стираете эти другие значения, что объясняет разницу в поведении. Я не уверен, почему NotifyFilters.CreationTime не перехватывает новый файл ... похожедолжен, не должен ли!

Похоже, что вы изолировали NotifyFilter от LastWrite, игнорируя другие аспекты FileSystemWatcher. Добавление в FileName решило проблему для меня.

Вы по-прежнему можете вызвать исключение, если файлы уже существуют в папке C:\TEST2\, но это очень простая настройка, которую можно выполнить до File.Move, если необходимо.

0 голосов
/ 22 января 2019

Ответ очевиден .. Вы передаете путь к папке в File.Move в файле и пути к файлу.

File.Move (file, path2 + "\" + System.IO.Path.GetFileName (file));

добавлен 1 символ в теле

...