Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations biv343 on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

File Access in timestamp order 2

Status
Not open for further replies.

ianLP59

Programmer
Jun 11, 2008
2
GB
I wish to access files for reading and subsequent processing in a given folder. I need to process them in exactly the order they were written to the folder in. Using FindFirst and FindNext does not appear to do this. How would I go about this ?
 
There's many ways to do it, but I'll describe the VCL way this time - TList:

Pop a button and a memo on a form if you want to try this, beyond that, better to ask back if there are any questions (for the file system, generally it comes back sorted by name but not always - anything else related to data, sorting is common enough):

Code:
unit Tsort;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
  ListRec = record
    Name: String;
    Time: Integer;
  end;
  PListRec = ^ListRec;

var
  Form1: TForm1;

implementation

{$R *.DFM}

function MyCompareFunc(Item1, Item2: Pointer): Integer;
  // Compare returns < 0 if Item1 is less and Item2,
  // 0 if they are equal
  // and > 0 if Item1 is greater than Item2.
  var
    res: integer;
  begin
    res := 0;
    if PListRec(Item1)^.Time > PListRec(Item2)^.Time then
      Res := 1
    else
      if PListRec(Item1)^.Time = PListRec(Item2)^.Time then
        Res := 0
      else
        if PListRec(Item1)^.Time < PListRec(Item2)^.Time then
          Res := -1;
    Result := Res;
  end;

procedure TForm1.Button1Click(Sender: TObject);
var
  MySearchRec: TSearchRec;
  errorcode: integer;
  SRec: PListRec;
  MyList: TList;
  i: integer;
begin
  MyList := TList.Create;
  try
    // form list here
    errorcode :=  FindFirst('C:\Windows\*.EXE', faAnyFile, MySearchRec);
    try
      while errorcode = 0 do
        begin
          New(SRec);
          SRec^.Name := MySearchRec.Name;
          SRec^.Time := MySearchRec.Time;
          MyList.Add(SRec);
          errorcode := FindNext(MySearchRec);
        end;
    finally
      FindClose(MySearchRec);
    end;
   // now sort it
   MyList.Sort(MyCompareFunc);
   // output the result
   for i := 0 to (MyList.Count - 1) do
     begin
       SRec := MyList.Items[i];
       Memo1.Lines.Add(SRec^.Name + ',' + IntToStr(SRec^.Time));
     end;
  finally
    // deallocate the whole list
    for i := 0 to (MyList.Count - 1) do
      begin
        SRec := MyList.Items[i];
        Dispose(SRec);
      end;
    MyList.Destroy;
  end;
end;

end.

----------
Measurement is not management.
 
Did you find Glenn's code useful? It is polite to thank someone who has spent some time helping you.

You might find this code a bit simpler but it achieves the same effect of displaying a list of files in file time order in a memo control:
Code:
const
  DirectoryPath = 'C:\data\';

procedure TForm1.Button1Click(Sender: TObject);
var
  tsr: TSearchRec;
  list: TStringList;
  x: integer;
begin
  list := TStringList.Create;
  list.Sorted := true;
  try
// Build list of files in time creation order
    if FindFirst( DirectoryPath + '*.*', 0, tsr ) = 0 then begin
      repeat
        list.Append( Format( '%.8x %s', [ tsr.Time, tsr.Name ] ) );
      until FindNext( tsr ) <> 0;
      FindClose( tsr );
    end;
// Process these files one at a time
    for x := 0 to list.count - 1 do
      Process( DirectoryPath + Copy( list[x], 9, Length(list[x]) ) );
  finally
    list.free;
  end;
end;

procedure TForm1.Process(filename: string);
begin
  memo1.Lines.Append( filename );
end;
The code uses TStringList rather than TList because TStringList can be sorted by setting the Sorted property to true. This avoids the requirement to write a sort routine. As each file name is added to the StringList it is prepended with the file time which ensures the filenames are sorted correctly. Once the list is built up each filename is passed to a procedure called Process which does whatever you want - in the above example it adds it to the memo.

Andrew
Hampshire, UK
 
Thanks guys. I am actually quite a polite person !!


Seriously, many thanks

Ian (Hampshire,UK)

 
The code uses TStringList rather than TList because TStringList can be sorted by setting the Sorted property to true.

Doing that runs a sort much like was described. Since TStringList is a descendent of TList, it can (and is) coded to call TList.Sort with a generic comparison routine. It becomes much trickier when you have multiple fields and varying conditions on sort (ascending or descending? How do I handle keys with multiple fields?).

Then since you won't always be working with strings, it's useful to be able to know some knowledge of sorting methods. TList usually suffices for something generic where performance isn't a complete concern and there isn't something better for the situation.

----------
Measurement is not management.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top