Avatar billede KurtG Forsker
21. marts 2023 - 17:55 Der er 2 kommentarer og
1 løsning

Delphi. Rekursiv kald stopper

Hej.
Jeg har ca 33.000 billedfiler.
Filerne er i nogle undermapper med følgende struktur:
FællesOvermappe
- A01
- A02
.....
- s39
- s40
Der er omkring 700 undermapper.
Inde i hver mappe ligger der op til 900 jpg-filer, der to og to skal samles til et billede og og det samlede billede derefter gemmes.
Mit problem er, at programmet stopper når den første (A01) undermappe er gennemløbet.
Jeg fandt kernen til programmet på nettet (jeg kan ikke genfinde det), og efter lidt tilretninger ser det således ud: 
(Filnavnene er altid sådan: A02-234a(eller b).jpg)

Function FileLook(Filespec: string): Boolean;
var
  validres, DotPos, Acnt, Bcnt: integer;
  SearchRec: TSearchRec; {required by 'FindFirst and FindNext' functions }
  Flname, Fnm: string;  //c:\Hofmansen\Alle Bearbejdede\Alle_A-B_filer\*.*
  {SearchRec does not return the full path in the name variable in the record,
  so 'DirPath' is used to store the full path name, and 'FullPathName' holds the Full Path Name plus the file name or filter spec while 'Flname' holds the filter or filename}
begin
  DirPath := ExtractFilePath(FileSpec); {keep track of the path ie: c:\folder\}
  Result:= DirectoryExists(DirPath);    {Check for valid directory - include FileCtrl in the uses statement}
  If not Result then exit;              {Invalid directory then exit}
  Flname := ExtractFileName(FileSpec);  {keep track of the name or filter}
  validres := FindFirst(FileSpec, faAnyFile, SearchRec); {find first file}
  while validres = 0 do              {if a matching file exists loop}
  begin
    If (SearchRec.Name[1] <> '.') then  {ignore . and .. dirs}
    begin
      count := count+1;
      FullPathName := DirPath + SearchRec.Name;
      Fnm := SearchRec.Name;;
      if AnsiPos(ExtractFileExt(SearchRec.Name), '.jpg') > 0 then
      Begin
        //Er det en A eller B-fil
        DotPos := Pos('.',Fnm);
        if (Fnm[DotPos-1] = 'a') OR (Fnm[DotPos-1] = 'A') then
        Begin
          FileAName := FullPathName;  //Bruges i prog. til at samle billederne
          Acnt := count;
        End;
        if (Fnm[DotPos-1] = 'b') OR (Fnm[DotPos-1] = 'B') then
        Begin   
          FileSaveName := Fnm;  //Til SamlFiler
          FileBName := FullPathName;
          Bcnt := count;
          //Er de lige efter hinanden
          if Acnt+1 = Bcnt then
          Begin  //Her kan billedbehndlingen foretages
            SamlFiler();    //Virker OK med samling og gemme
          End;
        End;
        application.processmessages();  //For at kunne stoppe programmet
      End;
      If (SearchRec.Attr and faDirectory > 0) then {it is a directory, not a file}
        FileLook(FullPathName+'\'+ Flname);
        {the above line is the recursive call to search the subdirectory.
        The trailing slash is added to the path as well as the filter filter or filename}
    end; {end if statement}
    validres:=FindNext(SearchRec); {get next record before continuing conditional while loop}
  end; {end while loop}
end; {end function}

Nogen forslag til hvad jeg gør forkert.
Avatar billede KurtG Forsker
21. marts 2023 - 17:58 #1
Jeg glemte at fortælle, at programmet startes med dette:
procedure TForm1.Button1Click(Sender: TObject);
begin
  count := 0;
  FileLook('c:\Hofmansen\Alle Bearbejdede\Alle_A-B_filer\*.*');
end;
Avatar billede arne_v Ekspert
27. marts 2023 - 15:57 #2
Der er noget ved den kode som jeg ikke kan lide.

Her er noget andet kode som outputter hvad det laver så man kan følge det.


program findab;

uses
  sysutils;

procedure process(a, b : string);

begin
  writeln('>>>> ' + a + ' and ' + b);
end;

procedure recurse(dir : string);

var
  ctx : TSearchRec;
  status : integer;
  ext, name : string;
  a, b : string;

begin
  writeln('Processing directory: ' + dir);
  status := FindFirst(dir + '\*.*', faAnyFile, ctx);
  while status = 0 do begin
    ext := ExtractFileExt(ctx.Name);
    name := Copy(ctx.Name, 1, Length(ctx.Name) - Length(ext));
    if (ext = '.jpg') or (ext = '.JPG') or (ext = '.jpeg') or (ext = '.JPEG') then begin
      if name.EndsWith('a') then begin
          a := dir + '\' + ctx.Name;
      end else if name.EndsWith('b') then begin
          b := dir + '\' + ctx.Name;
          process(a, b);
      end else begin
        writeln('Ignoring non-a/b file: ' + ctx.Name);
      end;
    end else if (ctx.Attr and faDirectory) <> 0 then begin
      if ctx.Name[1] <> '.' then begin
        recurse(dir + '\' + ctx.Name);
      end else begin
        writeln('Ignoring pseudo directory: ' + ctx.Name);
      end;
    end else begin
      writeln('Ignoring irrelevant file extension: ' + ctx.Name);
    end;
    status := FindNext(ctx);
  end;
end;

begin
  recurse('\Work\z');
  readln;
end.
Avatar billede KurtG Forsker
28. marts 2023 - 11:50 #3
Tak for programmet, Arne, det virker.
Jeg havde brugt megen tid på at finde fejlen i mit oprindelige program, men opgav til sidst.
I stedet fik jeg et program til at virke, som lavede en filliste. Den filliste kørte jeg så igennem med et andet program, der samlede billederne. Det blev jeg faktisk færdig med i forgårs. Programmet tog knap 2 timer til at sammenlægge de ca. 33.000 billeder.

Ved at se på listen herunder ser det ud til, at det oprindelige rekursive program ikke vender tilbage fra et rekursivt kald på rette måde, men jeg fandt aldrig ud af hvorfor.

Mit oprindelige rekursive programs listning:
c:\Test\
c:\Test\A08\
c:\Test\A08\A11\
c:\Test\A08\A11\A12\
c:\Test\A08\A11\A12\A13\
c:\Test\A08\A11\A12\A13\A14\
c:\Test\A08\A11\A12\A13\A14\A15\
c:\Test\A08\A11\A12\A13\A14\A15\A16\
c:\Test\A08\A11\A12\A13\A14\A15\A16\A17\
c:\Test\A08\A11\A12\A13\A14\A15\A16\A17\A19\
c:\Test\A08\A11\A12\A13\A14\A15\A16\A17\A19\A20\
c:\Test\A08\A11\A12\A13\A14\A15\A16\A17\A19\A20\A21\
c:\Test\A08\A11\A12\A13\A14\A15\A16\A17\A19\A20\A21\A22\
c:\Test\A08\A11\A12\A13\A14\A15\A16\A17\A19\A20\A21\A22\A23\
c:\Test\A08\A11\A12\A13\A14\A15\A16\A17\A19\A20\A21\A22\A23\A25\
c:\Test\A08\A11\A12\A13\A14\A15\A16\A17\A19\A20\A21\A22\A23\A25\A26\
c:\Test\A08\A11\A12\A13\A14\A15\A16\A17\A19\A20\A21\A22\A23\A25\A26\B08\
c:\Test\A08\A11\A12\A13\A14\A15\A16\A17\A19\A20\A21\A22\A23\A25\A26\B08\B15\
c:\Test\A08\A11\A12\A13\A14\A15\A16\A17\A19\A20\A21\A22\A23\A25\A26\B08\B15\B16\
c:\Test\A08\A11\A12\A13\A14\A15\A16\A17\A19\A20\A21\A22\A23\A25\A26\B08\B15\B16\B20\
c:\Test\A08\A11\A12\A13\A14\A15\A16\A17\A19\A20\A21\A22\A23\A25\A26\B08\B15\B16\B20\B22\
c:\Test\A08\A11\A12\A13\A14\A15\A16\A17\A19\A20\A21\A22\A23\A25\A26\B08\B15\B16\B20\B22\B24\


Arnes liste, der fungerer korrekt:
C:\Test\
C:\Test\\A08
C:\Test\\A11
C:\Test\\A12
C:\Test\\A13
C:\Test\\A14
C:\Test\\A15
C:\Test\\A15\r04
C:\Test\\A16
C:\Test\\A17
C:\Test\\A19
C:\Test\\A20
C:\Test\\A21
C:\Test\\A22
C:\Test\\A23
C:\Test\\A25
C:\Test\\A26
C:\Test\\B08
C:\Test\\B08\Renamed
C:\Test\\B15
C:\Test\\B15\Renamed
C:\Test\\B16
C:\Test\\B16\Renamed
C:\Test\\B20
C:\Test\\B20\Renamed
C:\Test\\B22
C:\Test\\B22\Renamed
C:\Test\\B24
C:\Test\\B24\Renamed
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester