C ++ Directory Watching - Как определить, что копия закончилась - PullRequest
7 голосов
/ 07 февраля 2012

У меня есть папка, в которую копируются файлы. Я хочу смотреть и обрабатывать файлы, как только они будут скопированы в каталог. Я могу определить, находится ли файл в каталоге, с помощью опроса (моя текущая реализация) или в некоторых тестах с использованием API-интерфейсов Windows из нескольких примеров, которые я нашел в Интернете.

Проблема в том, что я определяю, когда файл создается впервые, а он все еще копируется. Это делает мою программу, которой необходим доступ к файлу, из-за ошибок (потому что файл еще не завершен). Как я могу определить не когда началось копирование, а когда закончилось копирование? Я использую C ++ в Windows, поэтому ответ может зависеть от платформы, но, если возможно, я бы предпочел, чтобы он не зависел от платформы.

Ответы [ 3 ]

4 голосов
/ 07 февраля 2012

Вы можете использовать либо блокировку файлов, либо специальное соглашение об именах.Самый простой - последний, и он будет работать примерно так:

Скажем, вы хотите переместить файл с именем «fileA.txt». При копировании его в каталог назначения вместо этого скопируйте его в «fileA.txt.partial»." или что-то типа того.По завершении копирования переименуйте файл из «fileA.txt.partial» в «fileA.txt».Таким образом, внешний вид "fileA.txt" является атомарным, насколько видит программа просмотра.

Другой вариант, как упоминалось ранее, - блокировка файлов.Поэтому, когда вы копируете файл с именем «fileA.txt», вы сначала создаете файл с именем «fileA.txt.lock».Когда копирование завершено, вы просто удаляете файл блокировки.Когда наблюдающая программа видит «fileA.txt», она должна проверить, существует ли «fileA.txt.lock», если она существует, она может подождать или повторно посетить этот файл в будущем при необходимости.

2 голосов
/ 07 февраля 2012

Вы не должны опрашивать.Используйте FindFirstChangeNotification (http://msdn.microsoft.com/en-us/library/windows/desktop/aa364417%28v=vs.85%29.aspx) для просмотра каталога на предмет изменений.

Затем используйте функции ожидания (http://msdn.microsoft.com/en-us/library/windows/desktop/ms687069%28v=vs.85%29.aspx) для ожидания уведомлений об изменениях.

Обзор и примеры здесь: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365261%28v=vs.85%29.aspx

Я не уверен, как именно можно определить завершение записи файла. Ответ Эвана Терана - хорошая идея.

0 голосов
/ 16 ноября 2018

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

bool IsFileDownloadComplete(const std::wstring& dir, const std::wstring& fileName) 
{
    std::wstring originalFileName = dir + fileName;
    std::wstring tempFileName = dir + L"temp";

    while(true)
    {
        int ret = rename(convertWstringToString(originalFileName).c_str(), convertWstringToString(tempFileName).c_str());
        if(ret == 0)
            break;      

        Sleep(10);
    }   

    /** File is not open. Rename to original. */
    int ret = rename(convertWstringToString(tempFileName).c_str(), convertWstringToString(originalFileName).c_str());
    if(ret != 0)
        throw std::exception("File rename failed"); 

    return true;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...