【问题标题】:Delphi: Delete files in a directory older than X days and/or having a special file mask (*.xxx)Delphi:删除目录中早于 X 天和/或具有特殊文件掩码 (*.xxx) 的文件
【发布时间】:2019-01-23 06:33:02
【问题描述】:

语言: Delphi 10.1 Berlin

问题:
有一个包含测量文件(*.csv)和其他文件的目录。
每隔几个小时就会创建一个新的测量文件。
我需要删除该文件夹中所有早于特定天数的.csv 文件。不应触及所有其他文件类型。

问题:
Delphi 中是否有任何内置函数可以完成这项工作?如果没有,有什么有效的方法来解决这个问题?

【问题讨论】:

    标签: datetime delphi wildcard delete-file


    【解决方案1】:

    我没有找到针对该特定问题的 Delphi 内置函数。
    这个功能对我有用:

    function TUtilities.DeleteFilesOlderThanXDays(
        Path: string;
        DaysOld: integer = 0; // 0 => Delete every file, ignoring the file age
        FileMask: string = '*.*'): integer;
    var
      iFindResult : integer;
      SearchRecord : tSearchRec;
      iFilesDeleted: integer;
    begin
      iFilesDeleted := 0;
      iFindResult := FindFirst(TPath.Combine(Path, FileMask), faAnyFile, SearchRecord);
      if iFindResult = 0 then begin
        while iFindResult = 0 do begin
          if ((SearchRecord.Attr and faDirectory) = 0) then begin
            if (FileDateToDateTime(SearchRecord.Time) < Now - DaysOld) or (DaysOld = 0) then begin
              DeleteFile(TPath.Combine(Path, SearchRecord.Name));
              iFilesDeleted := iFilesDeleted + 1;
            end;
          end;
          iFindResult := FindNext(SearchRecord);
        end;
        FindClose(SearchRecord);
      end;
      Result := iFilesDeleted;
    end;
    

    【讨论】:

    • 这是“老派”方式。我假设使用 System.IOUtils 和 TDirectory 的解决方案也可以。
    • 至少这种方法避免了 IOUtils 的所有堆分配,这是一个历史上漏洞百出的单元 fwiw
    • 我会说FindClose 名义上放错了位置-它应该遵循if iFindResult = 0 语句(否则,如果FindFirst 返回0,则不会执行FindClose)并且@987654327 @ 是多余的,因为 while 将处理 FindFirst 返回 0 的情况。
    • @Magoo findclose 函数关闭成功的 FindFirst(和 FindNext)文件搜索。它释放了 SearchResults 中搜索所使用的资源。如果 FindFirst 没有找到任何内容,则不需要调用 findclose,但如果找到,则必须调用 findclose,即使随后的 FindNext 调用失败。
    • @Magoo stackoverflow.com/questions/32357314/… 特别是答案下的评论与这里相符。
    【解决方案2】:
    procedure DeleteFilesOlderThan(
      const Days: Integer;
      const Path: string;
      const SearchPattern: string = '*.*');
    var
      FileName: string;
      OlderThan: TDateTime;
    begin
      Assert(Days >= 0);
      OlderThan := Now() - Days;
      for FileName in TDirectory.GetFiles(Path, SearchPattern) do
        if TFile.GetCreationTime(FileName) < OlderThan then
          TFile.Delete(FileName);
    end;
    

    【讨论】:

    • 为什么在一个例程中执行此操作不好?您的方法涉及两个单独的枚举,这对我来说似乎是个坏主意。
    • 我阅读了 OP,因为必须满足这两个要求(匹配掩码并且比某些天旧),因此您不能将搜索分成两个例程,您需要检查两个条件相同的例程。
    • 是的,这两个要求都必须满足,实际上已经做到了。 DaysOld 的默认值和 OP 答案中的相关评论使得该例程似乎有额外的意图 - 通过掩码删除文件。基本上使用 DeleteFilesOlderThanXDays('C:\') 之类的东西删除文件会使代码不清楚。阅读代码的其他人可能不确定其含义:它是要删除所有文件(那么例程名称是什么?)还是您只是忘记指定参数?它可能需要额外的输入,但显式代码比隐式代码更好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-17
    • 2020-03-11
    • 1970-01-01
    • 2013-05-16
    • 2017-07-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多