Удалить файлы старше даты
В настоящее время я работаю над программой 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();