Avatar billede dl Nybegynder
01. juli 2004 - 22:26 Der er 21 kommentarer og
1 løsning

Hvorfor virker det i det ene program med ikke i det andet

Procedure Savefile( DirectoryToFile: String; SearchDirectory: String;  SearchRec: TSearchRec );
var
  Fil: TextFile;
begin
  AssignFile(Fil, DirectoryToFile);
  if FileExists(DirectoryToFile) then
    Append(Fil)
  else
  begin
    ReWrite(Fil);
  end;
  Writeln(Fil, SearchDirectory + ';' + SearchRec.Name + ';' + IntToStr(SearchRec.Size) + ';');
  CloseFile(Fil);
end;

Function Findfiles( Directory: String; FilterFiles: String; IncludeSubDir: Boolean; SaveDirectoryToFile: String ): Integer;
var
  SearchRec: TSearchRec;
begin
  if FindFirst(IncludeTrailingBackslash(Directory) + FilterFiles,faAnyFile,SearchRec) = 0 then
  begin
    repeat
      if (SearchRec.Attr and faDirectory) = faDirectory then
      begin
        if (SearchRec.Name <> '.') and (SearchRec.Name <> '..') and ( IncludeSubDir = True ) then
          FindFiles(IncludeTrailingBackslash(Directory) + SearchRec.Name,'*.*', True, SaveDirectoryToFile );
        end
        else
        begin
          SaveFile(SaveDirectoryToFile, Directory, SearchRec);
        end;
    until FindNext(SearchRec) <> 0;
    FindClose(SearchRec);
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Findfiles('C:\Documents and Settings\admin\Skrivebord\min findfunktion\test', '*.*', True, 'MineData.csv');
  Label1.Caption := IntToStr(Listbox1.Count);
end;

------------------

Den kode virker i et lille test program jeg har lavet.
filen
Sti;filenavn;Størrelse
Dette virker.

Når jeg så kopier koden over i et andet program ( det rigtig ) og bruger koden på samme måde, så virker det bare ikke.
filen
Sti;..;0
Dette virker IKKE. HVORFOR ?

//dl
Avatar billede vallemanden Nybegynder
02. juli 2004 - 10:29 #1
hvilken fejl får du?
Avatar billede hrc Mester
02. juli 2004 - 11:03 #2
Det ud til at FindFiles er forkert opbygget idet den ikke gennemløber underkataloger hvis ikke den finder filen (forskellig fra *.*) i det katalog hvor du p.t. er.

Derved exitter den fra starten og kommer aldrig til at gennemløbe underkatalogerne.

Jeg kigger lidt på rutinen og ser om jeg kan vende tilbage med noget jeg tror virker.
Avatar billede dl Nybegynder
02. juli 2004 - 11:05 #3
Jeg få ikke nogen fejl.
Kun at den ikke skrive det i filen som den skal.
Men jeg har den SAMME kode i et andet program, og der virker den som den skal.
Avatar billede kammeyer Nybegynder
02. juli 2004 - 11:28 #4
Du har nok en anden IO håndtering der ikke går som den skal i det andet program.
Avatar billede hrc Mester
02. juli 2004 - 11:49 #5
Din FindFirst returnerer <> 0 hvis files som du søger efter ikke findes i kataloget - derved exitter den første gang hvis filen ligger i underkataloger

Prøv med disse rutiner (ikke grundigt testet, men det der er testet, virker):

procedure Savefile(const aDirectoryToFile, aSearchDirectory: string; const aSearchRec: TSearchRec );
var
  Fil: TextFile;
begin
  AssignFile(Fil, aDirectoryToFile);
  if FileExists(aDirectoryToFile) then
    Append(Fil)
  else
    Rewrite(Fil);

  try
    with aSearchRec do
      writeln(Fil,format('%s;%s;%d;',[aSearchDirectory,Name,Size]));
  finally
    CloseFile(Fil);
  end; // try
end;

function Findfiles(const aDirectory, aFilterFiles: string; const aIncludeSubDir: boolean; const aSaveDirectoryToFile: string): integer;
var
  Found : boolean;
  SearchRec: TSearchRec;
begin
  Found := FindFirst(IncludeTrailingBackslash(aDirectory) + '*',faAnyFile,SearchRec) = 0;
  try
    while Found do begin
      if (SearchRec.Attr and faDirectory) = faDirectory then begin
        if (SearchRec.Name[1] <> '.') and aIncludeSubDir then
          FindFiles(IncludeTrailingBackslash(aDirectory) + SearchRec.Name, aFilterFiles, aIncludeSubDir, aSaveDirectoryToFile );
      end
      else if MatchesMask(SearchRec.Name,aFilterFiles) then
        SaveFile(aSaveDirectoryToFile, aDirectory, SearchRec);
      Found := FindNext(SearchRec) = 0;
    end; // while
  finally
    FindClose(SearchRec);
  end; // try
end;
Avatar billede hrc Mester
02. juli 2004 - 11:50 #6
Desuden havde du en fejl i din FindNext. Der var flere uhensigtsmæssigheder...
Avatar billede dl Nybegynder
02. juli 2004 - 12:05 #7
hov hov... det er ikke også alle som er prof..  ;)
//dl
jeg vil afprøve den.
Avatar billede hrc Mester
02. juli 2004 - 12:15 #8
Ydelsesmæssigt er det nok meget hurtigere om du sender en TStrings med i stedet for et filnavn der åbner og lukker en fil hver gang der findes et match.

procedure TfrmMain.Button1Click(Sender: TObject);
var
  FileList : TStringList;
begin
  Screen.Cursor := crHourGlass;
  FileList := TStringList.Create;
  try
    Findfiles('c:\program files',Edit1.Text,true,FileList);
    FileList.SaveToFile('c:\Test.txt');
  finally
    FileList.Free;
    Screen.Cursor := crDefault;
  end; // try
end;

Den tilrettede funktion ser nu sådan ud (og SaveToFile forsvinder):

function Findfiles(aDirectory, aFileSpec: string; const aIncludeSubDir: boolean; aResultList : TStrings): integer;
var
  Found : boolean;
  SearchRec: TSearchRec;
begin
  aDirectory := IncludeTrailingBackslash(aDirectory);
  Found := FindFirst(aDirectory + '*',faAnyFile,SearchRec) = 0;
  try
    while Found do begin
      with SearchRec do
        if (Attr and faDirectory) = faDirectory then begin
          if (Name[1] <> '.') and aIncludeSubDir then
            FindFiles(aDirectory + Name, aFileSpec, aIncludeSubDir, aResultList);
        end
        else if MatchesMask(Name,aFileSpec) then
          aResultList.Add(format('%s;%s;%d;',[aDirectory,Name,Size]));

      Found := FindNext(SearchRec) = 0;
    end; // while
  finally
    FindClose(SearchRec);
  end; // try
end;
Avatar billede dl Nybegynder
02. juli 2004 - 12:45 #9
ja, jeg ved ikke hvad du bruger af version, men jeg bruger alså kun D6.
og den kan ikke finde: MatchesMask

function Findfiles(aDirectory, aFileSpec: string; const aIncludeSubDir: boolean; aResultList : TStrings): integer;
var
  Found : boolean;
  SearchRec: TSearchRec;
begin
...
        else if MatchesMask(Name,aFileSpec) then
          aResultList.Add(format('%s;%s;%d;',[aDirectory,Name,Size]));
...
end;

//dl
Avatar billede hrc Mester
02. juli 2004 - 12:46 #10
Bare for at gøre opmærksom på at det undrede mig at du skrev at det fungerede... ;-)
Avatar billede hrc Mester
02. juli 2004 - 12:49 #11
Du skal inkludere en unit der hedder Masks (og jeg håber den er med i 6'eren) - alternativt kan du ikke bruge * og ?, men må angive det filde filnavn og konvertere til store bogstaver osv, osv. Det er noget lettere med MatchesMask.

Noget med at bruge CompareText() eller SameText()
Avatar billede dl Nybegynder
02. juli 2004 - 14:18 #12
Hvorfor er det lige den ikke skriver noget i filen ?
Avatar billede dl Nybegynder
02. juli 2004 - 14:21 #13
Jeg ved at være ret sur på det her projekt. jeg har prøvet og prøvet.
Så du er velkommen til at få kildekoden. Og lave en funktion og søger mapper igemmen. og gemmer i en csv fil,  sti,filnavn,størrelse

//dl

Bare læg din email
Avatar billede hrc Mester
02. juli 2004 - 14:54 #14
Jeg ved ikke hvorfor den ikke skriver til fil - begge mine løsninger ovenfor (og brug den sidste, den er langt hurtigst), skriver de fundne filer i filen.

  // I Edit1 har jeg prøvet med sysutils.pas og med *.pas - begge virkede
  Findfiles('c:\program files',Edit1.Text,true,FileList);
  FileList.SaveToFile('c:\Test.txt'); // Har du glemt denne her??
Avatar billede dl Nybegynder
02. juli 2004 - 15:12 #15
jeg har brugt disse koder: Kommentar: hrc - 02/07-2004 12:15:40.
Nej, fordi, den gemmer en fil, med det navn som den skal. Der er bare ikke noget i filen. Derved kan jeg kun se: At det er noget i din kode.

var
  FileList : TStringList;
begin
  FileList := TStringList.Create;
  try
///  min sti, som den skal søge i unden \  :  Navnet på filen den skal gemme result i,  resten er din kode.
    Findfiles(IncludeTrailingBackslash(Edit1.text),DatabaseEdit.Text + '.csv',true,FileList);
    FileList.SaveToFile(DatabaseEdit.Text + '.csv');
  finally
...

????
//dl
Avatar billede hrc Mester
02. juli 2004 - 21:19 #16
Så er det nok fordi den ikke finder det der søges efter. Hvad kommer der med over i funktionen? Hvad står der i DatabaseEdit.Text

Du kan evt. sende mig programmet på hrc_public (a) hotmail.com.
Avatar billede dl Nybegynder
03. juli 2004 - 12:26 #17
Så fik jeg det til at virke... det var min fejl. sorry.
hvad betyder :
MatchesMask(Name,aFileSpec)?
aFileSpec?
format('%s;%s;%d;',[aDirectory,Name,Size]) ?

//dl
du skal nok få point.
Avatar billede hrc Mester
03. juli 2004 - 21:16 #18
MatchesMask er en funktion der kan fodres med et filnavn og så kan den sammenligne om den passer den filspecifikation som er angivet i aFileSpec (filspecifikationen som funktionen blev kaldt med), eks '*utils.?as' - det vil returnere true hvis filen er 'sysutils.pas'.

format-kommandoen er en anden måde at gøre ';' + Navn + ';' + IntToStr(Size) + ... på. %d bliver erstattet med et decimaltal, mens %s erstattes af en streng. I ovenstående brug vil den skrive katalog;filnavn;størrelse - akkurat som du kan læse i filen. Jeg foretrækker denne løsning fordi jeg synes det er mere læseligt

LandMand := 'Jens Hansen';
Storrelse = 35.324232;

  format('Her er din gård %s. Der er %2.4f tønder land',[LandMand,Storrelse])

kontra dette

  'Her er din gård ' + LandMand + '. Der er ' + FloatToStrFmt(Storrelse,2,4) + ' tønder land'

Det fylder mere og jeg skal kalde en funktion for at formatere størrelsen så der ikke kommer for mange decimaler på. Med "format" kan man, på den anden side, godt risikere at compilere noget der viser sig at være en fejl når man kører programmet:

  format('Is there life on %s?',[Storrelse]); // Skulle være en streng = 'Mars'

Linien forventede en streng (angivet ved %s) men fik Storrelse der er et flydende decimaltal. Det går fint at oversætte men giver nogle irriterende fejlmeddelelser når man kører programmet.

Du bruger tilsyneladende ikke den brugervenlige hjælp i Delphi, for der vil du kunne læse dig frem til det. Bare stil markøren på ordet og tryk F1.
Avatar billede dl Nybegynder
03. juli 2004 - 21:25 #19
hehe ... jo jeg bruger den ... men jeg er en amatør programmør, jeg har ingen udd inden for det, endnu.

Og jeg kender faktisk ikke rigtig nogen af de advanceret funktion/procedure og sætningen du bruger. Jeg tror det er der mit problem er, hvis du se hvad jeg mener.

citat: eks '*utils.?as' - det vil returnere true hvis filen er 'sysutils.pas'.

Jeg kender * fra windows som et wildcard .. men hvad er ?, er det bare et wildcard for et char ?

//dl
Avatar billede hrc Mester
03. juli 2004 - 21:37 #20
hehe retur. Jeg kan se at du ikke er vokset op med Dos og windows 3.0 (godt for det).

Begge tegn er rigtignok jokere.

Asterix (*) betyder alt kombinationer foran Utils, altså både "Utils.pas", "IOUtils.pas" og "SysUtils.pas" mens spørgsmålstegnet (?) kun kigger på forskellige varianter af et tegn "?as" vil finde "pas", "das" og "mas" men ikke "as" for der skal være tre bogstaver.
Avatar billede hrc Mester
03. juli 2004 - 21:39 #21
I øvrigt er "format" en almindeligt brugt funktion. MatchesMask fandt jeg ved et tilfælde og ja, den er lidt speciel. Meget nyttig når man gerne vil slippe for at lave noget der håndterer * og ?.
Avatar billede dl Nybegynder
03. juli 2004 - 22:34 #22
hehe .. jo jeg er vokset op med dos, sådan i en mild grad.
Jeg godkender lige dine svar.

//dl
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
Kategori
Kurser inden for grundlæggende programmering

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