delphi - 计算目录大小API?

问题描述:

任何人都知道其他方式获得directoy的大小,而不是通过计算文件的文件来计算它的大小?我对一些win32 API函数感兴趣。我已经谷歌关于这一点,但我没有找到相关的信息,所以我在这里问。delphi - 计算目录大小API?

PS:我知道如何通过使用findfirst和findnext来计算目录大小,并且总和所有文件的大小。

+0

它必须是API? – Ampere 2017-08-09 13:28:33

+0

@Allforfree - 没必要。 – RBA 2017-08-10 06:16:08

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

  • 某些文件系统(包括NTFS和Linux上的大多数文件系统)支持“硬链接”的概念。也就是说,同一个文件可能出现在多个地方。软链接(重分析点)带来同样的问题。
  • Windows允许将文件系统挂载到目录。例如:“C:\ DriveD”可能与“D:\”相同。
  • 你想在磁盘上的文件大小或文件的实际大小?
  • 你关心实际的DIRECTORY条目吗?他们也占用空间!
  • 你对你无权访问的文件做了什么?或者你没有浏览权限的目录?你数过这些吗?

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

+0

1)不关心那些...我只解析fadirectories 2)相同1 3)实际大小 4)不,我需要的大小文件夹内的文件 5)将安装“超级管理员”的权利 我明白。所以唯一的解决办法是使用我自己的.... 好吧,谢谢大家 最好的问候, – RBA 2010-07-22 12:20:11

+0

+1的答案。 http://blogs.msdn.com/b/oldnewthing/archive/2004/12/28/336219.aspx – Alex 2010-07-22 17:08:27

如果你已经知道如何做另一个级别,只需使用递归获得每个级别。当你的函数遍历当前目录时,如果它出现在子目录中,则递归地调用该函数以获取该子目录的大小。

+0

谢谢,但我已经说过,如果存在,我需要一些API函数。 – RBA 2010-07-22 10:37:58

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

+0

+1“其他东西也会使用它”。 – 2010-07-22 12:00:56

+0

yhea ...你是对的+1 – RBA 2010-07-22 12:16:56

您可以使用FindFile组件。它会递归你的目录。

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

许多重复查找第一个和查找下一个实现不考虑大容量文件的前面的例子。这些例子不会产生正确的结果。提供适应更大文件容量的递归例程。

{*----------------------------------------------------------------------------- 
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/

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

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; 

GetFileSize

{ 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。

+0

谢谢你的答案,事件它是在7年后来的:)原来的问题是D7。请在这里留下答案,如果适用,其他人可以使用它。 +1 – RBA 2017-08-10 07:58:55