6

我目前正在开发 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 天。如果我将 PC 的日期设置为 4 月 24 日,则会按预期创建和保存文件,如果我随后将 PC 的日期更改为 4 月 25 日,我希望这些文件会保留,因为它们不超过 2 天,但是,这情况并非如此,因为它们正在被删除。

日志年龄设置为,因此在我将日期更改为 4 月 26 日之前,我不会期望文件被删除。

我做错了什么,我查看了许多示例,包括有关 Stackoverflow删除使用 .NET 的目录中超过 3 个月大的文件的另一个问题,但它没有按照我的预期做。

4

3 回答 3

9

您被迫只考虑创建时间戳的日期部分,然后满足条件并且文件将被删除(较早)无论如何我建议对该代码进行一些修改:

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(),我想你不想每次都重新发明轮子来检查路径是否以尾部反斜杠结尾。
  • I/O 操作可能会失败!始终检查异常。
于 2012-04-24T09:58:25.593 回答
2

file.Delete 确实比 File.Delete(path) 更有意义,而 Path.Combine() 比使用 string.Format 更有意义。

我偶然发现了这个答案,不知道为什么在谷歌上花了很长时间之后我没有找到它,但这似乎已经解决了这个问题。DateTime.Compare 如何检查日期是否小于 30 天?. 另一个问题是我使用的是文件创建时间,但对于我的场景,使用 lastWriteTime.date 更有意义。

于 2012-04-24T10:16:17.223 回答
0

我想一个额外的问题必须在

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

您的文件类型为FileSystemInfo。也许您想使用file.Name。示例:假设目录为“c:\”,文件指向“c:\myfile.log”,您的代码将尝试删除“ c:/c:\myfile.log ”。我很难猜出你在这些变量中到底有什么。

@HenkHolterman 建议正确替换:

file.Delete();
于 2012-04-24T10:16:15.703 回答