Gal
asked on
Locating files
Hi,
I'm new to Delphi, and still using Delphi 2.0 (wow!),
I'm looking for a function to let me locate a file in the user's HD. FileSearch and FileExists both take parameters of directories, but there's no way to look in subdirs as well.
since I don't know where or whether the app that created the files I need to locate has been installed, I need to look for them. anybody got an idea? this is quite urgent!
I'm new to Delphi, and still using Delphi 2.0 (wow!),
I'm looking for a function to let me locate a file in the user's HD. FileSearch and FileExists both take parameters of directories, but there's no way to look in subdirs as well.
since I don't know where or whether the app that created the files I need to locate has been installed, I need to look for them. anybody got an idea? this is quite urgent!
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Whooah BoRiS! You're fast!
/// John
/// John
Appendix:
the faAnyFile declared in Delphi might not be enough, hence:
const
faNormal = $00000080;
faTemporary = $00000100;
faCompressed = $00000800;
faAnyFileEx = faReadOnly or faHidden or faSysFile or faVolumeID or faDirectory or faArchive or faNormal or faTemporary or faCompressed;
Just replace all occurances of faAnyFile with faAnyFileEx.
Without this, all files will NOT be found!
/// John
the faAnyFile declared in Delphi might not be enough, hence:
const
faNormal = $00000080;
faTemporary = $00000100;
faCompressed = $00000800;
faAnyFileEx = faReadOnly or faHidden or faSysFile or faVolumeID or faDirectory or faArchive or faNormal or faTemporary or faCompressed;
Just replace all occurances of faAnyFile with faAnyFileEx.
Without this, all files will NOT be found!
/// John
ASKER
Thanks, BoRiS, erajoj.
I will try it out this evening and let you know how it went.
Thanks!
(BTW, BoRiS, I understand you're almost a neighbour - Tel-Aviv? I'm in Herzeliya. (Israel).
I will try it out this evening and let you know how it went.
Thanks!
(BTW, BoRiS, I understand you're almost a neighbour - Tel-Aviv? I'm in Herzeliya. (Israel).
Gal
No sorry... I stay in South Africa...
Later
BoRiS
No sorry... I stay in South Africa...
Later
BoRiS
ASKER
OK, erajoj, I implemented that piece of code you gave me, but I still don't really get it - I mean, I went through the logic, and it does work (I tested it too, of course). what I don't get yet is how to be able to get the File's full name (UNC) to a string-type var to be able to figure out its path, (extractFileDir), its date (FileAge) etc., to figure out if I need to replace it with a new one, append to it, and so on.
Thanks
Gal
Thanks
Gal
Hi,
There are of course, as always, several ways to attack this problem. The files in the list are in full name format, provided the sDir parameter is a full UNC directory name.
To get a path out of the list you do as usual:
sPath := MyList[ 0 ]; // for example
To get the file time stamp, you just call FileGetDate:
FileDate := FileGetDate( sPath );
To convert the date to TDateTime format:
dtFile := FileDateToDateTime( FileDate );
Another way to do this is to modify the search function:
type
PFileData = ^TFileData;
TFileData = record
Path, Name: string;
Time : TDateTime;
Size, Attr : Integer;
end;
...
function NewFindFiles( sDir, sMask: string; rgFileData: TList; bRecursively: Boolean ): Integer;
var
SR: TSearchRec;
pfd: PFileData;
begin
Result := 0;
if not Assigned( rgsFiles ) then Exit;
if sDir[ Length( sDir )] <> '\' then AppendStr( sDir, '\' ); // fix dir
if FindFirst( sDir + sMask, faAnyFile, SR ) = 0 then repeat
if ( SR.Attr and faDirectory ) <> faDirectory then begin
New( pfd );
rgFileData.Add( pfd );
with pfd^ do begin
Name := SR.Name;
Path := sDir;
Size := SR.Size;
Attr := SR.Attr;
Time := FileDateToDateTime( SR.Time );
end;
end;
until FindNext( SR ) <> 0;
FindClose( SR );
// recursive part...
if bRecursively then begin
if FindFirst( sDir + '*.*', faAnyFile, SR ) = 0 then repeat
if (( SR.Attr and faDirectory ) = faDirectory ) and ( SR.Name[1] <> '.' )
then FindFiles( sDir+SR.Name+'\', sMask, rgsFiles, bRecursively );
until FindNext( SR ) <> 0;
FindClose( SR );
end;
Result := rgsFiles.Count;
end;
Then, to use it:
var
myfiledata: PFileData;
MyFileDataList: TList;
...
if ( NewFindFiles( 'c:\', '*.txt', MyFileDataList, True ) > 0 ) then begin
myfiledata := MyFileDataList[ 0 ];
with myfiledata^ do begin
if ( ( Date-Time ) > 7 ) then ... /// more than a week old!
FullFilename := Path + Name;
end;
end;
You just have to clean up after you. MyFileDataList.Clear or MyFileDataList.Free is NOT enough. You still have data on your heap, so:
for iIndex := 0 to MyFileDataList.Count - 1 do
Dispose( PFileData( MyFileDataList[ iIndex ] ) );
MyFileDataList.Free;
Thats about it.
/// John
There are of course, as always, several ways to attack this problem. The files in the list are in full name format, provided the sDir parameter is a full UNC directory name.
To get a path out of the list you do as usual:
sPath := MyList[ 0 ]; // for example
To get the file time stamp, you just call FileGetDate:
FileDate := FileGetDate( sPath );
To convert the date to TDateTime format:
dtFile := FileDateToDateTime( FileDate );
Another way to do this is to modify the search function:
type
PFileData = ^TFileData;
TFileData = record
Path, Name: string;
Time : TDateTime;
Size, Attr : Integer;
end;
...
function NewFindFiles( sDir, sMask: string; rgFileData: TList; bRecursively: Boolean ): Integer;
var
SR: TSearchRec;
pfd: PFileData;
begin
Result := 0;
if not Assigned( rgsFiles ) then Exit;
if sDir[ Length( sDir )] <> '\' then AppendStr( sDir, '\' ); // fix dir
if FindFirst( sDir + sMask, faAnyFile, SR ) = 0 then repeat
if ( SR.Attr and faDirectory ) <> faDirectory then begin
New( pfd );
rgFileData.Add( pfd );
with pfd^ do begin
Name := SR.Name;
Path := sDir;
Size := SR.Size;
Attr := SR.Attr;
Time := FileDateToDateTime( SR.Time );
end;
end;
until FindNext( SR ) <> 0;
FindClose( SR );
// recursive part...
if bRecursively then begin
if FindFirst( sDir + '*.*', faAnyFile, SR ) = 0 then repeat
if (( SR.Attr and faDirectory ) = faDirectory ) and ( SR.Name[1] <> '.' )
then FindFiles( sDir+SR.Name+'\', sMask, rgsFiles, bRecursively );
until FindNext( SR ) <> 0;
FindClose( SR );
end;
Result := rgsFiles.Count;
end;
Then, to use it:
var
myfiledata: PFileData;
MyFileDataList: TList;
...
if ( NewFindFiles( 'c:\', '*.txt', MyFileDataList, True ) > 0 ) then begin
myfiledata := MyFileDataList[ 0 ];
with myfiledata^ do begin
if ( ( Date-Time ) > 7 ) then ... /// more than a week old!
FullFilename := Path + Name;
end;
end;
You just have to clean up after you. MyFileDataList.Clear or MyFileDataList.Free is NOT enough. You still have data on your heap, so:
for iIndex := 0 to MyFileDataList.Count - 1 do
Dispose( PFileData( MyFileDataList[ iIndex ] ) );
MyFileDataList.Free;
Thats about it.
/// John
ASKER
Hi erajoj.
I just noticed that they routed the point for this question you answered for me to BoRiS. I don't know why, but I guess it's because something I did or didn't do?
Anyway, the points clearly belong to you, so, if there's a way to reroute them, please let me know so I can do that
Sorry for the inconvenience.
Gal.
I just noticed that they routed the point for this question you answered for me to BoRiS. I don't know why, but I guess it's because something I did or didn't do?
Anyway, the points clearly belong to you, so, if there's a way to reroute them, please let me know so I can do that
Sorry for the inconvenience.
Gal.
Hi Gal.
Don't be sorry!
The points are not important at all if you're content with the answer!
BoRiS gave you a good answer and deserves the points.
/// John
Don't be sorry!
The points are not important at all if you're content with the answer!
BoRiS gave you a good answer and deserves the points.
/// John
ASKER
Well, thanks any way to both of you.
This session really got me going with my program here.
Thanks a lot and keep up the good work.
Gal.
This session really got me going with my program here.
Thanks a lot and keep up the good work.
Gal.
It searches using regular expression in any UNC directory, and puts all matching filenames in a TStrings list:
function FindFiles( sDir, sMask: string; rgsFiles: TStrings; bRecursively: Boolean ): Integer;
var
SR: TSearchRec;
begin
Result := 0;
if not Assigned( rgsFiles ) then Exit;
if sDir[ Length( sDir )] <> '\' then AppendStr( sDir, '\' ); // fix dir
if FindFirst( sDir + sMask, faAnyFile, SR ) = 0 then repeat
if ( SR.Attr and faDirectory ) <> faDirectory then rgsFiles.Add( sDir+SR.Name );
until FindNext( SR ) <> 0;
FindClose( SR );
// recursive part...
if bRecursively then begin
if FindFirst( sDir + '*.*', faAnyFile, SR ) = 0 then repeat
if (( SR.Attr and faDirectory ) = faDirectory ) and ( SR.Name[1] <> '.' )
then FindFiles( sDir+SR.Name+'\', sMask, rgsFiles, bRecursively );
until FindNext( SR ) <> 0;
FindClose( SR );
end;
Result := rgsFiles.Count;
end;
Usage:
FindFiles( 'c:\', '*.txt', ListBox1.Items, True );
or
MyStrings := TStringList.Create;
cLog := FindFiles( '\\server\logs\', '*.log', MyStrings, False );
etc...
I hope this will work in D2!
/// John