01. juli 2004 - 22:26Der 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 ?
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.
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.
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;
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.
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;
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;
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.
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
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??
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 ...
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]) ?
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.
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 ?
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.
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 ?.
hehe .. jo jeg er vokset op med dos, sådan i en mild grad. Jeg godkender lige dine svar.
//dl
Synes godt om
Ny brugerNybegynder
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.