2010-07-22 54 views
2

任何人都知道其他方式獲得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

回答

4

獲取一個目錄的大小是一個相當大的問題,主要是因爲它是你無法定義的。問題示例:

  • 某些文件系統(包括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

1

如果你已經知道如何做另一個級別,只需使用遞歸獲得每個級別。當你的函數遍歷當前目錄時,如果它出現在子目錄中,則遞歸地調用該函數以獲取該子目錄的大小。

+0

謝謝,但我已經說過,如果存在,我需要一些API函數。 – RBA 2010-07-22 10:37:58

2

我不認爲有這樣的API。我不認爲Windows知道答案。即它必須使用Marcelo指出的技術遞歸地搜索樹並彙總每個文件夾。
如果有這樣一個API調用可用,那麼其他東西也會使用它,Windows將能夠立即告訴你文件夾的大小。

+0

+1「其他東西也會使用它」。 – 2010-07-22 12:00:56

+0

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

0

許多重複查找第一個和查找下一個實現不考慮大容量文件的前面的例子。這些例子不會產生正確的結果。提供適應更大文件容量的遞歸例程。

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

2

我已經有了列出文件夾(和子文件夾)的文件和讀取文件大小的功能。所以,我只寫了一個把這兩個放在一起的小程序。

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