views:

479

answers:

3

In Delphi 2007 how can I make a program to read the first file and then close it to read the second one and so on until the last file?

+3  A: 

Are you trying to read every file in a directory? Try this class. This isn't my original code but I've modified and customized it a bit. It'll give you all the filenames that match criteria you set in a string list that you can pass to TFilestream.

unit findfile;

interface

uses
  Classes;

type
   TFileAttrKind = (ffaReadOnly, ffaHidden, ffaSysFile, ffaDirectory, ffaArchive, ffaAnyFile);
   TFileAttr = set of TFileAttrKind;

   TFindFile = class(TObject)
   private
      s: TStringList;

      fSubFolder : boolean;
      fAttr: TFileAttr;
      FPath : string;
      FBasePath: string;
      fFileMask : string;
      FDepth: integer;

      procedure SetPath(Value: string);
      procedure FileSearch(const inPath : string);
      function cull(value: string): string;
   public
      constructor Create(path: string);
      destructor Destroy; override;

      function SearchForFiles: TStringList;

      property FileAttr: TFileAttr read fAttr write fAttr;
      property InSubFolders : boolean read fSubFolder write fSubFolder;
      property Path : string read fPath write SetPath;
      property FileMask : string read fFileMask write fFileMask ;
   end;

implementation

{$WARN SYMBOL_PLATFORM OFF}
{$WARN UNIT_PLATFORM OFF}
uses
   Windows, SysUtils, FileCtrl;

constructor TFindFile.Create(path: string);
begin
   inherited Create;
   FPath := path;
   FBasePath := path;
   FileMask := '*.*';
   FileAttr := [ffaReadOnly, ffaDirectory, ffaArchive];
   s := TStringList.Create;
   FDepth := -1;
end;

procedure TFindFile.SetPath(Value: string);
begin
   if fPath <> Value then
   begin
      if (Value <> '') and (DirectoryExists(Value)) then
         fPath := IncludeTrailingPathDelimiter(Value);
   end;
end;

function TFindFile.SearchForFiles: TStringList;
begin
   s.Clear;
   try
      FileSearch(Path);
   finally
      Result := s;
   end;
end;

function TFindFile.cull(value: string): string;
begin
   result := StringReplace(value, FBasePath, '', []);
end;

destructor TFindFile.Destroy;
begin
   s.Free;
   inherited Destroy;
end;

procedure TFindFile.FileSearch(const InPath : string);
var Rec  : TSearchRec;
    Attr : integer;
begin
   inc(FDepth);
   try
      Attr := 0;
      if ffaReadOnly in FileAttr then
         Attr := Attr + faReadOnly;
      if ffaHidden in FileAttr then
         Attr := Attr + faHidden;
      if ffaSysFile in FileAttr then
         Attr := Attr + faSysFile;
      if ffaDirectory in FileAttr then
         Attr := Attr + faDirectory;
      if ffaArchive in FileAttr then
         Attr := Attr + faArchive;
      if ffaAnyFile in FileAttr then
         Attr := Attr + faAnyFile;

      if SysUtils.FindFirst(inPath + FileMask, Attr, Rec) = 0 then
         try
            repeat
               if (Rec.Name = '.') or (Rec.Name = '..') then
                  Continue;
               s.Add(cull(inPath) + Rec.Name);
            until SysUtils.FindNext(Rec) <> 0;
         finally
            SysUtils.FindClose(Rec);
         end;

      If not InSubFolders then
         Exit;

      if SysUtils.FindFirst(inPath + '*.*', faDirectory, Rec) = 0 then
         try
            repeat
               if ((Rec.Attr and faDirectory) <> 0)  and (Rec.Name <> '.') and (Rec.Name <> '..') then
               begin
                  FileSearch(IncludeTrailingPathDelimiter(inPath + Rec.Name));
               end;
            until SysUtils.FindNext(Rec) <> 0;
         finally
            SysUtils.FindClose(Rec);
         end;
   finally
      dec(FDepth);
   end;
end;

end.
Mason Wheeler
thank u but is this code work on delphi 2007
As far as I know it will.
Mason Wheeler
but I want it as VCL form application
This code is fine for a VCL forms application. Leave it in a separate unit, and 'use' that unit. Your main thread (that manages the GUI) will handle how things are displayed. Mason's code helps you manage the files. It's good to keep those functions separate.
Argalatyr
Right. This code is for getting a list of files. Once you've got that, it's easy to use a TFileStream and a for loop to open each one in turn and do whatever you want to them. If you give some more specific information about what you want to do (preferably in a separate question) we can give you some more specific and helpful answers.
Mason Wheeler
This code works in all Delphi versions.
Osama ALASSIRY
A: 

DIFileFinder might be something that you would like.

Bob S
+1  A: 

If you want to repeat an action, then what you want is called a loop. Delphi comes with three reserved words for loops: for, repeat, and while. All are documented in the help file; I think the overarching topic is called structured statements. You would do well to read about them.

A traditional for loop is most appropriate when you already have an array or list of things you want to process. In your case, probably a list of file names. You could write the loop like this:

for i := 0 to High(FileNames) do begin ... end;

or this:

for i := 0 to Pred(FileNames.Count) do begin ... end;

Then you would refer to FileNames[i] within the loop to get the file name of the current iteration. There's also a new-style for loop that you would use when the thing that contains your file names has an enumerator or iterator available. Then you would write the loop like this:

for name in FileNames do begin ... end;

While and repeat loops are used when you don't necessarily know before the loop starts how many times you'll need to run the code. You could use that in conjunction with the FindFirst and FindNext Delphi functions. For example:

if FindFirst('*.txt', faAnyFile, SearchResult) = 0 then try
  repeat
    // Do something with SearchResult.Name
  until FindNext(SearchResult) <> 0;
finally
  SysUtils.FindClose(SearchResult);
end;
Rob Kennedy