Как я могу контролировать блокировку файла, чтобы увидеть, когда он будет выпущен? [C ++] - PullRequest
0 голосов
/ 19 мая 2009

Я ищу способ создания программы на неуправляемом c ++, которая ждет, пока файл не будет разблокирован (поскольку он больше не используется) и чем-то занимается. Мне не повезло найти, как это сделать, любая помощь будет признательна!

ОБНОВЛЕНИЕ: Возможно, я ответил на свой вопрос, см. Ниже и скажите мне, что вы думаете ..

ОБНОВЛЕНИЕ: Все, что действительно важно, - это то, что файл доступен для записи, не имеет значения, используется ли он по-прежнему.

Ответы [ 5 ]

2 голосов
/ 19 мая 2009

Примерно так будет ждать, не тратя впустую циклы процессора.

HANDLE h = FindFirstChangeNotification("C:\Path to folder holding file", FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE);

while(true)
{
    if (CheckLockFile("C:\Path to file"))
    {
        // Do something
        break;
    }

    WaitForSingleObject(h, APPROPRIATE_TIMEOUT_VALUE);
    FindNextChangeNotification(h);
}

bool CheckLockFile(char* FilePath)
{
    HANDLE fh = CreateFile(FilePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0,NULL);
    if (fh == INVALID_HANDLE_VALUE)
    {
        return false; 
    }
    CloseHandle(fh);

    return true;
}

Предполагается, что приложение с блокировкой файла имеет открытый файл для записи.

1 голос
/ 19 мая 2009

Создайте цикл, который вызывает :: CreateFile () каждые 5 секунд, пока это не будет успешно выполнено. Передайте 0 в аргументе dwShareMode, чтобы убедиться, что нет другого процесса, у которого был открыт файл.

0 голосов
/ 20 мая 2009

Просто используйте Системную блокировку Уведомления о файлах

0 голосов
/ 19 мая 2009

Звучит так, будто вы хотите получить доступ к файлу после снятия блокировки другой программой. UNIX (и Cygwin) дают вам такое поведение, просто блокируя файл.

Использование чего-то вроде ScopeGuard может сделать File_locker ненужным, но если вы не используете ScopeGuard, сделайте так:

UNIX:

#include <stdexcept>
#include <string>
#include "sys/file.h" //flock
#include "sys/fcntl.h" //open

class File_locker {
    int file_descriptor;
  public:
    File_locker(std::string filename)
    {
        // you can use errno to determine why the open/flock failed,
        // but this is a demo, not production code

        file_descriptor = ::open(filename.c_str(), O_RDWR);
        if (file_descriptor < 0)
            throw std::runtime_error((std::string("unable to open file ")
                + filename).c_str());
        if (::flock(file_descriptor, LOCK_EX)) {
            ::close(file_descriptor);
            throw std::runtime_error((std::string("unable to flock file ")
                + filename).c_str());
        }
    }
    ~File_locker()
    {
        ::flock(file_descriptor, LOCK_UN); // don't forget to unlock
        ::close(file_descriptor);
    }
};

В Windows кажется, что вам нужно опросить файл.

Windows

#include <string>
#include "windows.h"

class File_locker {
    HANDLE file_handle;
    static const int MAX_TRIES = 10;
    static const int SLEEP_INTERVAL = 500;

  public:
    File_locker(std::string filename)
    {
        // you can use GetLastError() to determine why the open failed,
        // but this is a demo, not production code
        for (int i = 0; i < MAX_TRIES; ++i) {
            file_handle = ::CreateFile(filename.c_str(),
                                       GENERIC_READ | GENERIC_WRITE,
                                       0,
                                       NULL,
                                       OPEN_EXISTING,
                                       FILE_ATTRIBUTE_NORMAL,
                                       NULL);
            if (file_handle != INVALID_HANDLE_VALUE)
                return;
            ::Sleep(SLEEP_INTERVAL);
            }
            throw std::runtime_error((std::string("unable to open file ")
                + filename).c_str());
    }
    ~File_locker()
    {
        ::CloseHandle(file_handle);
    }
};

Используйте это так:

#include <fstream>
#include <stdexcept>

// .. define File_locker, as above

int main()
{
    try {
        File_locker fl("filename.txt");
        // once fl is constructed, nobody else has the file locked
        std::fstream file("filename.txt");
        // ...
        return 0;
    }
    catch (std::runtime_error& ex)
    {
        // just bail
        return 1;
    }
}
0 голосов
/ 19 мая 2009

Вот одно из возможных решений моей проблемы, кто-нибудь видит проблему с этим?

#include <iostream>
#include <fstream>
#include <windows.h>
using namespace std;
void main(int argc, char ** argv) {
    if (argc < 2 || argc > 2) {
        return;
    }

    ofstream myfile;
    myfile.open(argv[1], ios_base::app);
    while (!myfile.is_open()) { Sleep(100); myfile.open(argv[1], ios_base::app); }
    myfile.close();

    // file should now be unlocked..
}

Еще раз спасибо!

ОБНОВЛЕНИЕ: изменен код, чтобы быть более полным.

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