Efficient way to find file with highest number in Delphi

I have a file with a fixed pattern (CONST_) and a running number (XXXX) like this: CONST_XXXX.XYZ.

I am looking for an efficient way to get the file with the highest number in Delphi. Traversing with FindFirst / FindNext seems to be inefficient, if there are many files.

Answers


It is well known that finding the maximum of a list, in general, requires all items to be checked. And I believe that the most efficient way to do that is to use FindFirstFile/FindNextFile or related APIs. It's hard to imagine that there will be any real way to improve on the official system API for enumerating files.

That was certainly the opinion offered here: Is there a faster alternative to enumerating folders than FindFirstFile/FindNextFile with C++? Note that I am rejecting out of hand the option of parsing the file system by hand. I don't regard that as being very practical.

On the other hand, this answer offers hope that FindFirstFileEx with FindExInfoBasic and FIND_FIRST_EX_LARGE_FETCH may lead to better performance than plain old FindFirstFile.

You may need to look for an alternative solution to your problem, one that does not involve repeated enumerations of a directory full of files. Perhaps using a database so that you can take advantage of indexing. In fact, it is plausible that the built-in indexing service could be of use.


How about something like this:

for I := 0 to MAX_DIGITS - 4
begin
    S := 'CONST_' + StringOfChar('0', I);
    for C := '9' downto '1' do
    begin
      if FindFirst(S + C + '*.XYZ', faAnyFile, SearchResult) = 0 then
      begin
          //Code to iterate through the results using FindNext 
          //and returning "biggest" Name
          Result := SearchResult.FileName
          while FindNext(SearchResult) = 0 
            //ommitted: handling dirs / hidden
            if CompareStr(Result, SearchResult.FileName) < 0 then
              Result := SearchResult.FileName;
          //adding recursion instead of while... should make it even faster
          FindClose(SearchResult);
          Break;
      end; 
    end;
end;

Warning: this code has not been tested


An alternative would be

for I := 9999 downto 0 do
  begin
  FileName := Format ('CONST_%.4d.XYZ', [I]);
  if FileExists(FileName) then
    Break;
  end;  

Whether this is faster or not depends on the numbers you are expecting and on the performance of FileExists vs. FindFirst which I cannot comment on.


The another way is to read all occurring CONST_*.XYZ into FileListBox and then show the last.

procedure TForm1.Button1Click(Sender: TObject);
begin
FileListBox1.Directory:='D:\samples';
FileListBox1.Mask:='CONST_*.XYZ';
FileListBox1.Update;
Label1.Caption:= FileListBox1.Items[FileListBox1.Items.Count-1];
end;

To make it faster, you can use a function

function getRegion(filestr:string):Boolean;
begin
  if FindFirst(filestr, faAnyFile, searchResult) = 0 then result:=true else result:=false;
  if result then begin
     findN:=filestr;
  end;
end;

begin

SetCurrentDir('D:\samples');
  for i:=9 downto 0 do begin
    if getRegion(Format ('CONST_%.1d*.XYZ', [i])) then break;
  end;

FileListBox1.Directory:='D:\samples';
FileListBox1.Mask:=findN;
FileListBox1.Update;
Label1.Caption:= FileListBox1.Items[FileListBox1.Items.Count-1];

Update For test A) files were created from 0000-4999 For test B) files were created from 0000-9999 TestA made files from 0000 to only 4999 because user jpfollenius uses downto

from 0000 to 4999 = 5000 files from 9999 downto 4999 = 5000 files

Testtable TestA

Test B

I'm shure with more files 50000 files my solution loads 10000 filenames for example 50000 to 59999 that takes

  • moskito-x .................................. 0.345 seconds (tested)
  • pure FindFirst / FindNext .......... 0.390 seconds estimated to (0.039 * 10)

Need Your Help

retrieve section from UIButton in Header view in section in UITableview

ios objective-c uitableview

i have insert a UIButton in the header of the UITableView in every section, i want know if it's possible when pressed retrieve the section number, i add the button in this way:

Python string interpolation: only show necessary decimal places

python string formatting

If I have for example x = 40 I want the following result: