[Webinar] Streamline your web hosting managementRegister Today

x
?
Solved

Find a file in a Delphi application

Posted on 2015-01-14
8
Medium Priority
?
899 Views
Last Modified: 2015-01-14
Maybe this exists already so I do not have to code it by myself
I look for a function that will receive a filename, says myfile.txt as argument 1, a directory says mydir as argument 2 and the function will return the first occurrence (full name) of that file somewhere under the mydir structure ...
Thanks
0
Comment
Question by:LeTay
  • 3
  • 2
  • 2
  • +1
8 Comments
 
LVL 46

Expert Comment

by:aikimark
ID: 40549561
I don't think there's an intrinsic Delphi function to do this.  Normally, I would expect to see a solution that involves recursing through the directory tree, stopping when it finds the desired file.

Do you need to do this a lot or is this a one shot search?
How important is performance?
0
 
LVL 3

Expert Comment

by:lopem
ID: 40549624
Try this example code using FileSearch:

//Searching in the current directory and beyond
var
  myFile       : TextFile;
  fileName     : string;
  fullFilePath : string;
  dir1, dir2   : string;

begin
  // The file we will be searching for
  fileName := 'Test.txt';

  // Write to a text file in the current directory
  AssignFile(myFile, fileName);
  ReWrite(myFile);
  Write(myFile, 'Hello World');
  CloseFile(myFile);

  // Write to a text file to another directory
  AssignFile(myFile, 'C:\Program Files\'+fileName);
  ReWrite(myFile);
  Write(myFile, 'Hello World');
  CloseFile(myFile);

  // Define two directories where we want to search for the file
  dir1 := 'C:\No such directory';
  dir2 := 'C:\Program Files';

  // Search for the file
  fullFilePath := FileSearch(fileName, dir1+';'+dir2);

  // If we search now, we will find it in the current directory
  if fullFilePath = ''
  then ShowMessage(fileName+' not found')
  else ShowMessage(fullFilePath+' found OK');

  // Now delete Test.txt from the current directory and retry
  DeleteFile(fileName);

  // If we search now, we will find it in one of the search dirs
  fullFilePath := FileSearch(fileName, dir1+';'+dir2);
  if fullFilePath = ''
  then ShowMessage(fileName+' not found')
  else ShowMessage(fullFilePath+' found OK');
end;
0
 
LVL 28

Accepted Solution

by:
Sinisa Vuk earned 2000 total points
ID: 40549818
this is how to find file in subfolders using Findfirst, FindNext functions:
function FindInFolder(sFolder, sFile: String; bUseSubfolders: Boolean): String;
var
  sr: TSearchRec;
  i: Integer;
  sDatFile: String;
begin
  //finf file in current folder
  Result := '';
  sFolder := IncludeTrailingPathDelimiter(sFolder);
  if SysUtils.FindFirst(sFolder + sFile, faAnyFile - faDirectory, sr) = 0 then
  begin
    Result := sFolder + sr.Name;
    SysUtils.FindClose(sr);
    Exit;
  end;

  //not found .... search in subfolders
  if bUseSubfolders then
  begin
    //find first subfolder
    if SysUtils.FindFirst(sFolder + '*.*', faDirectory, sr) = 0 then
    begin
      try
        repeat
          if ((sr.Attr and faDirectory) <> 0) and (sr.Name <> '.') and (sr.Name <> '..') then //is real folder?
          begin
            //recursive call!
            Result := FindInFolder(sFolder + sr.Name, sFile, bUseSubfolders);
            if Length(Result) > 0 then Break; //found it ... escape
          end;
        until SysUtils.FindNext(sr) <> 0;  //...next subfolder
      finally
        SysUtils.FindClose(sr);
      end;
    end;
  end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  s: String;
begin
  s := FindInFolder('D:\Work', 'file.zip', True);
  if s <> '' then ShowMessage('Found: ' + s);
end;

Open in new window


Parameters to application you can get using ParamCount and ParamStr:
if ParamCount>=2 then  //more than one params
begin
  s := FindInFolder(ParamStr(2), ParamStr(1), True);
  if s <> '' then ShowMessage('Found: ' + s);
end;

Open in new window

0
The 14th Annual Expert Award Winners

The results are in! Meet the top members of our 2017 Expert Awards. Congratulations to all who qualified!

 
LVL 3

Expert Comment

by:lopem
ID: 40549863
Hi, Sinisa, your code takes care of subdirectories also?
0
 
LVL 28

Expert Comment

by:Sinisa Vuk
ID: 40549919
yes, if you put True (as third parameter) like in example.
0
 
LVL 3

Expert Comment

by:lopem
ID: 40549939
cool! Nice code
0
 
LVL 46

Expert Comment

by:aikimark
ID: 40549958
Another approach is to shell out a Dir /s /b highlevelpath\filename > somepath\dirlist.txt command and then read the contents of the dirlist.txt file.  You can even use wildcard characters in the file name.

I think there might have been a sysutils library or JEDI unit that had reasonably fast performance searching for files in a directory tree.

If you are using XE7 (maybe 6), you might try the parallel For loop to search the directory tree.
0
 

Author Comment

by:LeTay
ID: 40550190
Finally I wrote this, inspired by Sinisa who gets the points
I had already a recursive function to analyse a directory structure for other purposes...

function BTFileSearch(FileName,Dir:string):string;
var
 F:TSearchRec;
begin
 Result := '';
 FileName := LowerCase(FileName);
 if (FindFirst(Dir + '\*.*',faAnyFile,F) = 0)
  then repeat
   if (F.Name = '.') or (F.Name = '..') then Continue;
   if ((faDirectory and F.Attr) <> 0)
     then begin
       Result := BTFileSearch(FileName,Dir + '\' + F.Name);
       if (Length(Result) <> 0)
         then begin
           FindClose(F);
           Exit;
         end;
     end
     else begin
       if (LowerCase(F.Name) = FileName)
         then begin
           Result := Dir + '\' + FileName;
           FindClose(F);
           Exit;
         end;
     end;
  until (FindNext(F) <> 0);
 FindClose(F);
end;
0

Featured Post

Learn to develop an Android App

Want to increase your earning potential in 2018? Pad your resume with app building experience. Learn how with this hands-on course.

Question has a verified solution.

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

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…
This is an update to some code that someone else posted on Experts Exchange. It is an alternate approach, I think a little easier to use, & makes sure that things like the Task Bar will update.
How can you see what you are working on when you want to see it while you to save a copy? Add a "Save As" icon to the Quick Access Toolbar, or QAT. That way, when you save a copy of a query, form, report, or other object you are modifying, you…
Hi, this video explains a free download that you can incorporate into your Access databases, or use stand-alone for contact management. Contacts -- Names, Addresses, Phone Numbers, eMail Addresses, Websites, Lists, Projects, Notes, Attachments…
Suggested Courses

608 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