2006. május 19., péntek
How to find the size of a given directory
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;
Feliratkozás:
Megjegyzések küldése (Atom)
Nincsenek megjegyzések:
Megjegyzés küldése