Удалить файлы старше даты

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

DateTime creationTime = file.CreationTime.Date;
if (creationTime < DateTime.Now.AddDays(-logAge) && file.Name != currentLog)
{
    File.Delete(string.Format("{0}/{1}", directory, file));
}

Пока моя программа работает, она постоянно создает новые файлы, и отдельный поток проверяет, что файлы не старше, чем, скажем, 2 дня. Если у меня на компьютере установлена ​​дата 24 апреля, файлы будут созданы и сохранены в соответствии с ожиданиями, если я затем изменю дату ПК на 25 апреля, я буду ожидать, что файлы останутся, поскольку они не старше 2 дней, однако это это не так, поскольку они удаляются.

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

Что я делаю не так, я просмотрел много примеров, в том числе еще один вопрос о Stackru. Удалите файлы старше 3 месяцев в каталоге, используя.NET, но он не выполняет то, чего я ожидал.

3 ответа

Решение

file.Delete имеет больше смысла, чем File.Delete(путь) и Path.Combine() имеет гораздо больше смысла, чем использование string.Format.

Я наткнулся на этот ответ, не знаю, почему я не нашел его раньше, проведя целую вечность в Google, но, похоже, это решило проблему. DateTime.Compare, как проверить, если дата меньше 30 дней?, Другая проблема заключалась в том, что я использовал время создания файла, но для моего сценария было больше смысла использовать lastWriteTime.date.

Вы вынуждены учитывать только часть даты метки времени создания, тогда условие выполнено, и файл будет удален (ранее), в любом случае, я предлагаю несколько модификаций этого кода:

static class Helpers {
    public static void DeleteOldFiles(string folderPath, uint maximumAgeInDays,
                                      params string[] filesToExclude) {
        DateTime minimumDate = DateTime.Now.AddDays(-maximumAgeInDays);

        var filesToDelete = Directory.EnumerateFiles(folderPath)
            .Where(x => !IsExcluded(x, filesToExclude));

        foreach (var eligibleFileToDelete in filesToDelete)
            DeleteFileIfOlderThan(eligibleFileToDelete, minimumDate);
    }

    private const int RetriesOnError = 3;
    private const int DelayOnRetry = 1000;

    private static bool IsExcluded(string item, string[] exclusions) {
        return exclusions.Contains(item, StringComparer.CurrentCultureIgnoreCase);
    }

    private static void DeleteFileIfOlderThan(string path, DateTime date)
    {
        for (int i = 0; i < RetriesOnError; ++i) {
            try {
                var file = new FileInfo(path);
                if (file.CreationTime < date)
                    file.Delete();
            }
            catch (IOException) {
                System.Threading.Thread.Sleep(DelayOnRetry);
            }
            catch (UnauthorizedAccessException) {
                System.Threading.Thread.Sleep(DelayOnRetry);
            }
        }
    }
}

Заметки

  • Я все еще использую DateTime.NowЯ полагаю, что для такого рода операций вам не нужно точное измерение (и вы говорите о днях, чтобы у вашего потока было запланированное время в часах).
  • Если ваше приложение использует несколько файлов журнала, вы можете указать их все в качестве параметров, и они будут игнорироваться.
  • Если вы позвоните DeleteOldFiles с 0 для maximumAgeInDays тогда вы задержите все файлы журнала, которые не используются (как указано в списке исключений).
  • Иногда файлы могут использоваться (даже если это случается редко в вашем случае). DeleteFileIfOlderThan функция попытается удалить их после небольшой задержки (имитирует Explorer.exe поведение).

Вы можете вызвать эту функцию следующим образом:

Helpers.DeleteOldFiles(@"c:\mypath\", logAge, currentLog);

Еще несколько заметок:

  • Этот код не объединяет путь и имя файла, но если вам нужно сделать это, вы должны использовать Path.Combine()Я думаю, вы не хотите изобретать велосипед каждый раз, чтобы проверить, заканчивается ли путь завершающим обратным слешем или нет.
  • Операции ввода / вывода могут потерпеть неудачу! Всегда проверяйте наличие исключений.

Я думаю, что дополнительная проблема должна быть в

File.Delete(string.Format("{0}/{1}", directory, file));

Ваш файл имеет тип FileSystemInfo. Может быть, вы хотели использовать файл. Имя. Пример: допустим, каталогом является "c: \", а файл указывает на "c: \ myfile.log", ваш код попытается удалить " c: / c: \ myfile.log ". Мне трудно угадать, что именно у вас есть в этих переменных.

Правильная замена предложена @HenkHolterman:

file.Delete();
Другие вопросы по тегам