Как правильно открыть файл для удаления? - PullRequest
10 голосов
/ 09 августа 2011

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

Сейчас я использую 99% подход:

FileStream s = null;
try {
    s = new FileStream (
        path,
        FileMode.Open,
        FileAccess.ReadWrite,
        FileShare.None);
    // some stuff about the file is checked here
    s.Dispose ();
    // hope the file is not accessed by someone else...
    File.Delete (path);
    return true;
}
catch (IOException) {
    if (s !=null) s.Dispose ();
    return false;
}

Обычно это работает, но я подумал, что есть лучший способ избежать условия края.

Открытие файла с флагом DeleteOnClose не работает, поскольку указанная проверка (которая происходит после открытия с уже установленным флагом удаления) может указывать на то, что файл не должен быть удален.

Ответы [ 3 ]

7 голосов
/ 09 августа 2011

Примерно так:

    using (FileStream file = new FileStream(path,
       FileMode.Open,
       FileAccess.ReadWrite,
       FileShare.Delete))
    {
        // you can read the file here and check your stuff
        File.Delete(path);
    }

PS: обратите внимание на ключевое слово using. Это позволяет вам иметь более чистый код, поскольку он заботится о вызовах Dispose.

1 голос
/ 09 августа 2011

Прежде всего, вы подражаете выражению «использование», и вы делаете это неправильно. Вы должны утилизировать файловый поток только один раз, в предложении finally, а не два раза при попытке поймать. Но лучше использовать, используя.

using (FileStream s = new FileStream())
{
}

Во-вторых, вам лучше всего выбрать Transactional NTFS (одна из оболочек находится в библиотеке Nabu: https://dev.triflesoft.org/mercurial/nabu/),, однако Transactional NTFS ограничена NTFS и Windows Vista +, так что если вам нужна FAT16 / FAT32 или Windows XP, это не тот путь.


Вы также можете попробовать переместить / переименовать открытый файл, чтобы запретить доступ другим процессам, но это ограничено только NTFS AFAIR.


Если вам не нужно мгновенно удалять файл, вы можете использовать функцию SetupQueueDelete API настройки.

0 голосов
/ 09 августа 2011

Вы не можете полностью предотвратить возможность состояния гонки. Учитывая, что у вашей программы проблемы, если между проверкой и удалением файла произошли изменения, есть как минимум 2 обходных пути, которые я вижу:

  • Получить имя временного файла, переименовать файл в временный файл, выполнить проверку и переименовать при необходимости (может привести к новым проблемам в зависимости от вашей бизнес-логики)
  • Вы можете установить атрибут readonly для файла перед его проверкой.
...