How to find the size of a given directory (Views: 28)
Problem/Question/Abstract: I'm looking for a way to find the size of any given directory and all the files in that directory. I know when you look at the properties of a given directory you get the size, date, number of sub- directories, etc. That is the information that I'm looking for. Answer: Solve 1: unit DirectorySize; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TFrmDirectorySize = class(TForm) Button1: TButton; Memo1: TMemo; CbxFilesToo: TCheckBox; Memo2: TMemo; procedure Button1Click(Sender: TObject); procedure FormCreate(Sender: TObject); private public end; var FrmDirectorySize: TFrmDirectorySize; implementation {$R *.DFM} uses FileCtrl; function FormatNumber(ANumber: double): string; var p: integer; begin Result := Format('%n', [ANumber]); p := Pos(DecimalSeparator, Result); if p > 0 then Result := Copy(Result, 1, p - 1); end; function GetDirectorySize(APath: string; AList: TStrings; AFilesToo: boolean): longint; const indent: string = ''; var curItem: integer; dirSize: longint; kb: double; searchRec: SysUtils.TSearchRec; tmpS: string; begin if AFilesToo and (indent <> EmptyStr) then AList.Add(EmptyStr); curItem := AList.Add(indent + APath); Result := 0; if APath[Length(APath)] <> '\' then APath := APath + '\'; if FindFirst(APath + '*.*', faDirectory, searchRec) = 0 then repeat {Assure that it's a normal file} with searchRec do begin if Name[1] <> '.' then if (Attr and faDirectory > 0) then begin indent := indent + ' '; dirSize := GetDirectorySize(APath + Name + '\', AList, AFilesToo); Delete(indent, 1, 2); Result := Result + dirSize; end else begin Result := Result + searchRec.Size; if AFilesToo then begin {Memo2.Clear; Memo2.Lines.Add(Name);} AList.Add(indent + ' ' + Name + ' [' + FormatNumber(searchRec.Size) + ']'); end; end; end; Application.ProcessMessages; until FindNext(searchRec) <> 0; SysUtils.FindClose(searchRec); kb := Result / 1024.0; tmpS := ' (' + Format('%nk', [kb]) + ')'; AList[curItem] := AList[curItem] + ' [' + FormatNumber(Result) + tmpS + ']'; end; procedure TFrmDirectorySize.Button1Click(Sender: TObject); var directory: string; begin Memo1.Clear; Button1.Enabled := false; Cursor := crHourglass; Memo1.Lines.BeginUpdate; try Application.ProcessMessages; if SelectDirectory('Select A Directory', '', directory) then begin Caption := Directory; GetDirectorySize(directory, Memo1.Lines, CbxFilesToo.Checked); end; finally Cursor := crDefault; Button1.Enabled := true; Memo1.Lines.EndUpdate; end; end; procedure TFrmDirectorySize.FormCreate(Sender: TObject); begin Memo2.Clear; Icon.Assign(Application.Icon); end; end. Solve 2: uses Windows function CalcFolderSize(aRootPath: string): Int64; procedure Traverse(const aFolder: string); var Data: TWin32FindData; FileHandle: THandle; begin FileHandle := FindFirstFile(PCHAR(aFolder + '*'), Data); if FileHandle <> INVALID_HANDLE_VALUE then try repeat if (Data.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY > 0) and (Data.cFileName[0] <> '.') then Traverse(aFolder + Data.cFilename + '\') else Inc(Result, (Data.nFileSizeHigh * MAXDWORD) + Data.nFileSizeLow); until not FindNextFile(FileHandle, Data); finally Windows.FindClose(FileHandle); end; end; begin Result := 0; if aRootPath[Length(aRootPath)] <> '\' then aRootPath := aRootPath + '\'; Traverse(aRootPath); end; Solve 3: Most the examples of this I've seen return a 4-byte integer. That's mostly ok for file sizes, but a sum of file size can more easily exceed the 4Gb limit. This example uses and 8-byte (signed) integer: function DirectorySize(const sPath: TFileName): Int64; var rFind: TSearchRec; iSize: Int64; begin Result := 0; if SysUtils.FindFirst(IncludeTrailingBackslash(sPath) + '*', faAnyFile, rFind) = 0 then begin try repeat if rFind.Name <> StringOfChar('.', Length(rFind.Name)) then begin if (rFind.Attr and faDirectory) = faDirectory then Result := Result + DirectorySize(IncludeTrailingBackslash(sPath) + rFind.Name) else begin iSize := (Int64(rFind.FindData.nFileSizeHigh)shl32) or rFind.FindData.nFileSizeLow; Result := Result + iSize; end; end; until SysUtils.FindNext(rFind) <> 0; finally SysUtils.FindClose(rFind); end; end; end; |