user2858981
user2858981

Reputation: 255

Delphi - For each listbox item run a function and move item according to the function result

I have a listbox in which I list all files from a folder. For each element of the listbox I want to run a function. If the function result is false then I want to move the listbox item into a separate listbox called ListBox_fisiere_restore_vme. If the function result is true then I want to add the listbox item into a listbox called ListBox_continut_ftp. This should be ease to do.The problem is that no matter the function result the item is allways moved into the ListBox_fisiere_restore_vme.

The function i use for each listbox item:

function GetFileSize_mmg(const FileName: string): Int64;
var
  fad: TWin32FileAttributeData;
begin
 if not GetFileAttributesEx(PChar(FileName), GetFileExInfoStandard, @fad) then RaiseLastOSError;
  Int64Rec(Result).Lo := fad.nFileSizeLow;
  Int64Rec(Result).Hi := fad.nFileSizeHigh;
end;    

function does_size_changes(nume_fisier: string; interval: integer;Memo_loguri: TMemo): boolean;
var
  size1, size2: Int64;
begin
  size1:=0;
  size2:=0;  
  size1 := GetFileSize_mmg(nume_fisier);
  delay(interval);
  size2 := GetFileSize_mmg(nume_fisier);

  if size1 <> size2 then
  begin
    Result := true;
    Memo_loguri.Lines.Add(datetimetostr(now) + ' - filename "'+nume_fisier+'" grows');
  end
  else
  begin
    Result := false;
    Memo_loguri.Lines.Add(datetimetostr(now) + ' - filename "'+nume_fisier+'" is not in use');
  end;
end;

The loop that causes this issue has the following code:

procedure Tform2.OnSchedule_1_Trigger(Sender: TScheduledEvent);
var
nume_fisier:string;
i:integer;
begin
listbox_fisiere_in_uz.Clear;
listbox_fisiere_restore_vme.Clear;
DSiEnumFilesToSL(edit_watch_folder.text+edit_masca_fisiere.text, 0, listbox_fisiere_in_uz.Items, true, false );  
for i := ListBox_fisiere_in_uz.Items.count - 1 downto 0 do 
begin
   if does_size_changes(ListBox_fisiere_in_uz.Items[i], 1000, Memo_loguri) then        
    begin            
     listbox_continut_ftp.Items.Add(ListBox_fisiere_in_uz.Items[i]);
    end
     else
    begin
     ListBox_fisiere_restore_vme.Items.Add(ListBox_fisiere_in_uz.Items[i]);  
     end;
    end;

I don't see where I'm doing it wrong.

Upvotes: 0

Views: 1482

Answers (2)

David Schwartz
David Schwartz

Reputation: 1844

I suspect the problem you're seeing is related to the fact that you're running through the loop with the delay in series with the tests. If you have 100 files you're testing, it'll take 100 seconds, with one file tested every second. One thousand files will take 1000 seconds. If any given file doesn't change in that one-second window when it's examined, it'll give the results you're observing.

for i := 0 to n-1 do
begin
  s1 := sizeoffile( fn[i] );
  delay( 1000 ); // pause one second
  s2 := sizeoffile( fn[i] );

  if (s1 <> s2) then
    addToLog( 'file size of '+fn[i]+' DID change' )
  else
    addToLog( 'file size of '+fn[i]+' did NOT change' )
end;

Compare that behavior to this approach that will only take seconds to run regardless of 'n':

var
  initialFileSize, newFileSize : array of Int64;

. . .

// get initial file sizes
for i := 0 to n-1 do
  initialFileSize[i] := sizeoffile( fn[i] );

delay( 1000 ); // pause one second

// get new file sizes
for i := 0 to n-1 do
  newFileSize[i] := sizeoffile( fn[i] );

for i := 0 to n-1 do
begin
  if (initialFileSize[i] <> newFileSize[i]) then
    addToLog( 'file size of '+fn[i]+' DID change' )
  else
    addToLog( 'file size of '+fn[i]+' did NOT change' )
end;

The first approach is like trying to hit a moving target. The second approach captures the file states all at once, and measures changes all in the same relative gap of time. It will take only a few seconds to run.

I suspect the latter approach is closer to what you're intending.

Upvotes: 1

LHristov
LHristov

Reputation: 1123

How long is delay(interval)? Try to increase it.

But this is wrong concept. If delay(interval) is 100 msec this means you have more than minute and a half (100 sec) to loop 1000 files. If I were you I'd use a timer and few string grids instead of listboxes.

Each 2 column string grid can contain file name in column 0 and file size in column 1. Four grids - stringGrid_continut_ftp, stringGrid__fisiere_restore_vme, stringGrid_old and stringGrid_current.

Timer1.timer must get the default file names and sizes in stringGrid_current, compare them with stringGrid_old and and depending on result must insert a row in one of the first two string grids. At the end stringGrid_old must have all values from stringGrid_current and next timer event is ready to start.

Sorry for giving explanation only but right now I'm too tired of c++, wix and batch files and cannot focus to write quality delphi code. But I'm sure you'll get the idea.

Upvotes: 0

Related Questions