【问题标题】:delphi - calculate directory size API?delphi - 计算目录大小API?
【发布时间】:2010-07-22 10:08:46
【问题描述】:

除了通过计算文件和文件来计算它的大小之外,任何人都知道获取目录大小的其他方法吗?我对一些 win32 API 函数感兴趣。我已经用谷歌搜索过这个,但我没有找到相关信息,所以我在这里问。

PS:我知道如何使用 findfirst 和 findnext 计算目录大小,并对所有文件的大小求和。

【问题讨论】:

  • 一定是API?
  • @Allforfree - 没必要。

标签: windows winapi directory size delphi-7


【解决方案1】:

获取一个目录的大小是一个相当大的问题,主要是因为它是您无法定义的。问题示例:

  • 一些文件系统,包括 NTFS 和 Linux 上的大多数文件系统都支持“硬链接”的概念。也就是说,同一个文件可能会出现在多个地方。软链接(重解析点)也存在同样的问题。
  • Windows 允许将文件系统挂载到目录。示例:“C:\DriveD”可能与“D:\”相同。
  • 您想要磁盘上的文件大小还是文件的实际大小?
  • 您是否关心实际的 DIRECTORY 条目?它们还占用空间!
  • 您如何处理您无权访问的文件?还是您无权浏览的目录?你会数那些吗?

考虑到所有这些意味着唯一可能的实现是递归实现。你可以自己写或者希望你能找到一个现成的,但最终的表现是一样的。

【讨论】:

  • 1) 不关心那些...我将只解析 fadirectories 2) 与 1 相同 3) 实际大小 4) 不,我需要文件夹内文件的大小 5) 将以我理解的“超级管理员”权限安装。所以唯一的解决方案是使用我自己的......好的,谢谢大家最好的问候,
【解决方案2】:

我认为没有用于此的 API。我不认为 Windows 知道答案。也就是说,它必须使用 Marcelo 指出的技术递归搜索树并总结每个文件夹。
如果有这样的 API 调用可用,那么其他东西也会使用它,Windows 将能够立即告诉你文件夹的大小。

【讨论】:

    【解决方案3】:

    我已经有了列出文件夹(和子文件夹)文件的功能和读取文件大小的功能。所以,我只写了一个小程序,把这两者放在一起。

    ListFilesOf

    function ListFilesOf(CONST aFolder, FileType: string; CONST ReturnFullPath, DigSubdirectories: Boolean): TTSL;
    { If DigSubdirectories is false, it will return only the top level files,
      else it will return also the files in subdirectories of subdirectories.
      If FullPath is true the returned files will have full path.
      FileType can be something like '*.*' or '*.exe;*.bin'
      Will show also the Hidden/System files.
      Source Marco Cantu Delphi 2010 HandBook
    
       // Works with UNC paths}
    VAR
      i: Integer;
      s: string;
      SubFolders, filesList: TStringDynArray;
      MaskArray: TStringDynArray;
      Predicate: TDirectory.TFilterPredicate;
    
     procedure ListFiles(CONST aFolder: string);
     VAR strFile: string;
     begin
      Predicate:=
            function(const Path: string; const SearchRec: TSearchRec): Boolean
            VAR Mask: string;
            begin
              for Mask in MaskArray DO
                if System.Masks.MatchesMask(SearchRec.Name, Mask)
                then EXIT(TRUE);
              EXIT(FALSE);
            end;
    
      filesList:= TDirectory.GetFiles (aFolder, Predicate);
      for strFile in filesList DO
       if strFile<> ''                                                                                 { Bug undeva: imi intoarce doua intrari empty ('') }
       then Result.Add(strFile);
     end;
    
    begin
     { I need this in order to prevent the EPathTooLongException (reported by some users) }
     if aFolder.Length >= MAXPATH then
      begin
       MesajError('Path is longer than '+ IntToStr(MAXPATH)+ ' characters!');
       EXIT(NIL);
      end;
    
     if NOT System.IOUtils.TDirectory.Exists (aFolder)
     then RAISE Exception.Create('Folder does not exist! '+ CRLF+ aFolder);
    
     Result:= TTSL.Create;
    
     { Split FileType in subcomponents }
     MaskArray:= System.StrUtils.SplitString(FileType, ';');
    
     { Search the parent folder }
     ListFiles(aFolder);
    
     { Search in all subfolders }
     if DigSubdirectories then
      begin
       SubFolders:= TDirectory.GetDirectories(aFolder, TSearchOption.soAllDirectories, NIL);
       for s in SubFolders DO
         if cIO.DirectoryExists(s)                                                                     { This solves the problem caused by broken 'Symbolic Link' folders }
         then ListFiles(s);
      end;
    
     { Remove full path }
     if NOT ReturnFullPath then
      for i:= 0 to Result.Count-1 DO
       Result[i]:= TPath.GetFileName(Result[i]);
    end;
    

    获取文件大小

    { Works with >4GB files
      Source: http://stackoverflow.com/questions/1642220/getting-size-of-a-file-in-delphi-2010-or-later }
    function GetFileSize(const aFilename: String): Int64;
    VAR
       info: TWin32FileAttributeData;
    begin
     if GetFileAttributesEx(PWideChar(aFileName), GetFileExInfoStandard, @info)
     then Result:= Int64(info.nFileSizeLow) or Int64(info.nFileSizeHigh shl 32)
     else Result:= -1;
    end;
    

    最后:

    function GetFolderSize(aFolder: string; FileType: string= '*.*'; DigSubdirectories: Boolean= TRUE): Int64;
    VAR
       i: Integer;
       TSL: TTSL;
    begin
     Result:= 0;
     TSL:= ListFilesOf(aFolder, FileType, TRUE, DigSubdirectories);
     TRY
      for i:= 0 to TSL.Count-1 DO
       Result:= Result+ GetFileSize(TSL[i]);
     FINALLY
      FreeAndNil(TSL);
     END;
    end;
    

    请注意:
    1. 只能统计文件夹中某些文件类型的大小。例如在包含 BMP 和 JPEG 文件的文件夹中,如果您想要/需要,您只能获取 BMP 文件的文件夹大小。
    2. 支持多种文件类型,例如:'.bmp;.png'。
    3.您可以选择是否要读取子文件夹的大小。

    进一步改进:您可以通过消除 GetFolderSize 并将 GetFileSize 直接移动到 ListFilesOf 中来大幅减小代码大小

    保证可以在 Delphi XE7 上工作。

    【讨论】:

    • 感谢您的回答,事件将在 7 年后出现 :) 最初的问题是针对 D7。请在此处留下答案,以便其他人在适用时使用它。 +1
    【解决方案4】:

    如果您已经知道如何进行另一个级别,只需使用递归来获得每个级别。当您的函数遍历当前目录时,如果遇到子目录,则递归调用该函数以获取该子目录的大小。

    【讨论】:

    • 谢谢,但我已经说过如果存在我需要一些 api 函数。
    【解决方案5】:

    您可以使用 FindFile 组件。它将为您递归目录。

    http://www.delphiarea.com/products/delphi-components/findfile/

    【讨论】:

      【解决方案6】:

      前面许多重复查找优先和查找下一个实现的示例都没有考虑较大的文件容量。这些示例不会产生正确的结果。可以使用适应更大文件容量的递归例程。

      {*-----------------------------------------------------------------------------
       Procedure: GetDirSize
       Author:    archman
       Date:      21-May-2015
       @Param     dir: string; subdir: Boolean
       @Return    Int64
       -----------------------------------------------------------------------------}
      
      function TBCSDirSizeC.GetDirSize(dir: string; subdir: Boolean): Int64;
      var
        rec: TSearchRec;
        found: Integer;
      begin
        Result := 0;
        if dir[Length(dir)] <> '\' then
          dir := dir + '\';
        found := FindFirst(dir + '*.*', faAnyFile, rec);
        while found = 0 do
        begin
          Inc(Result, rec.Size);
          if (rec.Attr and faDirectory > 0) and (rec.Name[1] <> '.') and
            (subdir = True) then
            Inc(Result, GetDirSize(dir + rec.Name, True));
          found := FindNext(rec);
        end;
        System.SysUtils.FindClose(rec);
      end;
      

      请访问下面的链接以获取有关该过程的完整说明。 http://bcsjava.com/blg/wordpress/2015/06/05/bcs-directory-size-delphi-xe8/

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-02-06
      • 1970-01-01
      • 2010-11-26
      • 1970-01-01
      • 2011-03-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多