Solved

Directory and its Sub-Directories listing

Posted on 1997-06-10
3
454 Views
Last Modified: 2010-04-06


If I want to get a list of all sub-directories immediately
below a given directory.  

At the moment, I am currently using code like :

     IF FindFirst (in_dir_path + '*.*',
          (faDirectory), SearchRec) = 0 then
     begin
          IF DirectoryExists (in_dir_path + SearchRec.Name) Then
             in_out_Listbox.Items.Add (in_dir_path + SearchRec.Name + '\');
     end;

     While FindNext (SearchRec) = 0 do
     begin
          IF DirectoryExists (in_dir_path + SearchRec.Name) Then
             in_out_Listbox.Items.Add (in_dir_path + SearchRec.Name + '\');
     end;

The real pain is that the FindFirst / FindNext return all files
+ directories - hence the need for the DirectoryExists
check before adding the item to the listbox.

This isn't what I want - because for directories with many hundreds
of files and only a few sub-directories, this takes a few seconds.

Is there any way to list just the directories ?

I have also written code that extends the above to list
all sub-directories of a given directory - not just the directories
immediately below the given directory.

Does anybody have some good fast code to do this ?
0
Comment
Question by:moose032797
  • 2
3 Comments
 

Accepted Solution

by:
brittain earned 50 total points
ID: 1336961
Couple things:

1.  FindFirst() and FindNext() are just wrappers around the WINAPI FindFirstFile() and FindNextFile().  The optimal solution would be to write your own FindFirstDir(), etc.

2.  Small performance improvement can be gained by checking the Attr property of SearchRec rather than calling DirectoryExists().

3.  Larger performance improvement:  Build a string list in memory within your loop, then afterwards Assign the string list to the control.  The reason for this is each Items.Add() call sends a Windows message to the control, very slow.
0
 

Author Comment

by:moose032797
ID: 1336962
>The optimal solution would be to write your own
>FindFirstDir(), etc.

OK, but this relies on me being able to find the first dir and
then the next.

As I said above, I need to know how to do this in Delphi.

Moose
0
 

Expert Comment

by:brittain
ID: 1336963
As always, all things are possible with the source.  This is what I meant by write your own.  FindMatchingFile() and FindFirstDir() are straight out of the SYSUTILS.PAS.  (I added the Dir, of course).  The only change is marked by [srb] in the code.  Note, I didn't have to check FindNext()!

This is the quick solution.  These should probably be improved to better exist with SYSUTILS.PAS (i.e. FindMatchingFile() was a local function to the SYSUTILS.PAS unit).

function FindMatchingFile(var F: TSearchRec): Integer;
var
  LocalFileTime: TFileTime;
begin
  with F do
  begin
    while FindData.dwFileAttributes and ExcludeAttr <> 0 do
      if not FindNextFile(FindHandle, FindData) then
      begin
        Result := GetLastError;
        Exit;
      end;
    FileTimeToLocalFileTime(FindData.ftLastWriteTime, LocalFileTime);
    FileTimeToDosDateTime(LocalFileTime, LongRec(Time).Hi,
      LongRec(Time).Lo);
    Size := FindData.nFileSizeLow;
    Attr := FindData.dwFileAttributes;
    Name := FindData.cFileName;
  end;
  Result := 0;
end;


function FindFirstDir(const Path: string; Attr: Integer;
  var F: TSearchRec): Integer;
const
  //[srb]faSpecial = faHidden or faSysFile or faVolumeID or faDirectory;
  //[srb] Added the faAnyFile constant to this exclusion mask!
  faSpecial = faAnyFile or faHidden or faSysFile or faVolumeID or faDirectory;
begin
  F.ExcludeAttr := not Attr and faSpecial;
  F.FindHandle := FindFirstFile(PChar(Path), F.FindData);
  if F.FindHandle <> INVALID_HANDLE_VALUE then
  begin
    Result := FindMatchingFile(F);
    if Result <> 0 then FindClose(F);
  end else
    Result := GetLastError;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  f : TSearchRec;
  lt : TStringList;

begin
  lt := TStringList.Create;
  try
//    if (0 = FindFirst( 'c:\winnt\*.*', (faDirectory), f )) then begin
    if (0 = FindFirstDir( 'c:\winnt\*.*', (faDirectory), f )) then begin
      lt.Add(f.name);
//      while (0 = FindNext( f )) do
      while (0 = FindNext( f )) do
        lt.Add(f.name);

      ListBox1.Items.Assign( lt );
    end;
  finally
    lt.free;
  end;
end;

0

Featured Post

Are your AD admin tools letting you down?

Managing Active Directory can get complicated.  Often, the native tools for managing AD are just not up to the task.  The largest Active Directory installations in the world have relied on one tool to manage their day-to-day administration tasks: Hyena. Start your trial today.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Established in 1997, Technology Architects has become one of the most reputable technology solutions companies in the country. TA have been providing businesses with cost effective state-of-the-art solutions and unparalleled service that is designed…
Nobody understands Phishing better than an anti-spam company. That’s why we are providing Phishing Awareness Training to our customers. According to a report by Verizon, only 3% of targeted users report malicious emails to management. With compan…

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question