Удаляйте файлы, только если ВСЕ удаляются - избавьте невинных

Предположим, у меня есть структура каталогов, подобная следующей:

MyDirectory
> File1
> File2
> File3
> UndeletableFile
> File4

Предположим также, что я уже реализовал рекурсивный алгоритм для удаления содержимого папки, а затем самой папки и / или использовал одно из превосходных предложений здесь

Теперь вот уловка, к которой я не могу найти решение после некоторого поиска в Интернете и на SO:
Я хочу удалить всю папку, но я хочу сделать это только в том случае, если она будет успешной для каждого файла и подпапки, которые там находятся. Текущая реализация (из java.io.File.delete() если быть точным) удалит файл сразу после вызова и затем перейдет к следующему файлу. Если удаление папки не удастся на полпути, как в примере выше, будет UndeletableFile а также File5 так же как MyDirectory оставил в системе.

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

О чем я думал до сих пор:
Может быть, было бы разумно просто сначала переименовать все файлы, а не удалять их, вот так

MyDirectory
> File1temp
> File2temp
>...

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

Но эти швы очень неэффективны для меня, разве нет лучшего решения? Мне кажется, что это должно быть распространенной проблемой, пожалуйста, укажите ссылку, если я что-то упустил

3 ответа

Решение

Не существует абсолютно безопасного способа сделать это.

Лучше всего будет просмотреть все файлы и убедиться, что вы можете удалить их. Только если сканирование прошло успешно, вы можете пройти и выполнить фактическое удаление.

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

Единственной альтернативой будет сохранение копии всех файлов (т.е. перемещение их в корзину, хранение в zip-архиве и т. Д.) До тех пор, пока все удаления не будут выполнены успешно, и только после этого очистка корзины / удаление zip-файла - если не восстановить,

Но даже тогда что-то могло случиться, чтобы заблокировать восстановление.

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

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

private static RandomAccessFile raf;

public static void main(String[] args) throws IOException {
    lock();
    //do smth...
    release();
}

private static boolean lock() throws IOException {
    File f = new File("Semaphore.lck");
    raf = new RandomAccessFile(f, "rw");
    FileLock fl = raf.getChannel().tryLock();
    return fl != null;
}

private static void release() throws IOException {
    raf.close();
}

Аналогичный подход используется в инфраструктуре интеграции Apache Camel, посмотрите на его компонент File. Единственная проблема заключается в том, что второй процесс должен следовать тому же протоколу, иначе он не будет иметь никакого эффекта.

Вы можете сначала использовать неразрушающий метод, чтобы проверить, может ли быть удален какой-либо файл, например, в UNIX проверьте, доступен ли для записи сам файл и содержащий его каталог. Затем рекурсивно рассчитайте, какие каталоги можно удалить, а затем за второй проход удалите те файлы и каталоги, которые находятся в каталогах, рассчитанных на удаление. Проблема этого подхода заключается в том, что кто-то другой может изменять каталог или содержимое файла или разрешения во время операции, поэтому вы все равно можете получить неправильные результаты.

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

Не существует надежного метода, который бы работал на всех платформах при любых условиях, поскольку базовой файловой системой могут одновременно управлять другие процессы.

Для сценария с одним пользователем следует использовать двухэтапный подход, описанный в первом абзаце.

Другие вопросы по тегам