Wyszukiwanie kopii pliku

0

Witam, szukam kopii pliku na dysku lecz mam problem, mam 2 funkcje, jedna szuka pliku, gdy go znajdzie zapisuje jego nazwę,rozmiar i czas ost. modyfikacji:

procedure TForm1.FileSearchPrev(const PathName, FileName : string);
var
 sr : TSearchRec;
 sx : Integer;
 Path : String;
begin
Path:=IncludeTrailingBackslash(PathName);
sx  :=  FindFirst(Path + FileName, faAnyFile - faDirectory, sr);
if sx = 0 then
begin
  try
    repeat
      //dane
      nazwa:=sr.Name;
      time:=sr.Time;
      rozmiar:=sr.Size;
      exit;
    until FindNext(sr) <>0
    finally
    FindClose(sr);
  end;
end;
if FindFirst(Path + '*.*', faDirectory, sr) = 0 then
 try
   repeat
    if ((sr.Attr and faDirectory) <> 0)  and (sr.Name<>'.') and (sr.Name<>'..') then
     FileSearch(Path + sr.Name, FileName);
   until FindNext(sr) <> 0;
 finally
   FindClose(sr);
 end;
end; // wyszukiwanie

Ona działa wykonuje swoje zadanie.
2 funkcja to lekko zmofyfikowana funkcja powyżej, która ma mi wyszukać kopię tego pliku, doda wynik jeżeli zgadza się rozmiar, nazwa oraz data.

procedure TForm1.FileSearch(const PathName, FileName : string);
var
 sr1 : TSearchRec;
 sx : Integer;
 Path : String;
begin
Path:=IncludeTrailingBackslash(PathName);
sx  :=  FindFirst(Path + FileName, faAnyFile - faDirectory, sr1);
if sx = 0 then
begin
  try
    repeat
    if (nazwa = sr1.Name) //and (rozmiar = sr.Size) //and (time = sr.Time)
    then
      Memo1.Lines.Add(Path + sr1.Name);
    until FindNext(sr1) <>0
    finally
    FindClose(sr1);
  end;
end;
if FindFirst(Path + '*.*', faDirectory, sr1) = 0 then
 try
   repeat
    if ((sr1.Attr and faDirectory) <> 0)  and (sr1.Name<>'.') and (sr1.Name<>'..') then
     FileSearch(Path + sr1.Name, FileName);
   until FindNext(sr1) <> 0;
 finally
   FindClose(sr1);
 end;
end; // wyszukiwanie

Korzystam z gotowej pętli którą znalazłem w internecie dla przeszukiwania katalogów, myślę, że błąd może leżeć gdzieś tu, możecie zerknąć, jest to fragment kodu z funkcji powyżej?

if FindFirst(Path + '*.*', faDirectory, sr1) = 0 then
 try
   repeat
    if ((sr1.Attr and faDirectory) <> 0)  and (sr1.Name<>'.') and (sr1.Name<>'..') then
     FileSearch(Path + sr1.Name, FileName);
   until FindNext(sr1) <> 0;
 finally
   FindClose(sr1);
 end;
end;
0
  1. wywal z pierwszej funkcji zmienną sx bo nie jest w ogóle potrzebna,
  2. stosuj szkielet "znalezionej w sieci funkcji" do wyszukiwania,
  3. zamiast IncludeTrailingBackslash stosuj IncludeTrailingPathDelimiter,
  4. zapoznaj się z tym artykułem a zrozumiesz jak wykonać rekurencyjne wyszukiwanie plików na dysku,
  5. zaprzyjaźnij się z debugerem - pomoże Ci znaleźć ewentualne błędy.

No dobra, z nudów naszkicowałem (w Delphi 7) prosty algorytm rekurencyjnie wyszukujący pliki o danym rozszerzeniu i wyświetlający drzewo w oknie konsoli:

program FindFiles;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  Classes;

const
  INDENT_SIZE = 2;

  { extract last directory name }
  function ExtractDirName(const APath: AnsiString): AnsiString;
  var
    iPathLen, I: Word;
  begin
    iPathLen := Length(APath);

    for I := Pred(iPathLen) downto 1 do
      if APath[I] = '\' then
      begin
        Result := Copy(APath, I + 1, iPathLen - I - 1);
        Exit;
      end;
  end;

  { search files }
  procedure SearchFiles(const ATabSize: Byte; const APath, AExtension: AnsiString);
  var
    srDir, srFile: TSearchRec;
  begin
    WriteLn(StringOfChar(' ', ATabSize), '+ [ ', ExtractDirName(APath), ' ]');

    { files }
    if FindFirst(APath + AExtension, faAnyFile, srFile) = 0 then
    begin
      repeat
        if ((srFile.Attr and faDirectory) <> faDirectory) and
           ((srFile.Name <> '.') and (srFile.Name <> '..')) then
          WriteLn(StringOfChar(' ', ATabSize + INDENT_SIZE), '- ', srFile.Name);
      until FindNext(srFile) <> 0;
      FindClose(srFile);
    end;

    { directories }
    if FindFirst(APath + '*.*', faDirectory, srDir) = 0 then
    begin
      repeat
        if ((srDir.Attr and faDirectory) = faDirectory) and
           ((srDir.Name <> '.') and (srDir.Name <> '..')) then
          SearchFiles(ATabSize + INDENT_SIZE, APath + srDir.Name + '\', AExtension);
      until FindNext(srDir) <> 0;
      FindClose(srDir);
    end;
  end;

const
  ROOT_PATH = 'C:\WINDOWS\';
  DIR_NAME = 'Help\';
  FILTER = '*.*m*';
var
  slParents: TStrings;
  iTabSize, I: Byte;
begin
  { parents }
  slParents := TStringList.Create();
  try
    iTabSize := 0;
    ExtractStrings(['\'], [], PChar(ROOT_PATH), slParents);

    for I := 0 to Pred(slParents.Count) do
    begin
      WriteLn(StringOfChar(' ', iTabSize), '+ [ ', slParents[I], ' ]');
      Inc(iTabSize, INDENT_SIZE);
    end;
  finally
    slParents.Free;
  end;

  { searching }
  SearchFiles(iTabSize, ROOT_PATH + DIR_NAME, FILTER);
  ReadLn;
end.

czego wyniekiem będzie (na moim komputerze):

+ [ C: ]
  + [ WINDOWS ]
    + [ Help ]
      - ciadmin.htm
      - ciquery.htm
      - ieakmmc.chm
      - ieeula.chm
      - iesupp.chm
      - iexplore.chm
      - ixqlang.htm
      - migwiz.htm
      - migwiz2.htm
      + [ Tours ]
        + [ htmlTour ]
        + [ mmTour ]
        + [ WindowsMediaPlayer ]
          + [ Audio ]
            - snd.htm
            + [ Wav ]
          + [ Cnt ]
            - contents.htm
          + [ Css ]
          + [ Img ]
            + [ Btn ]
            + [ WMarks ]
          + [ Scr ]
          + [ Video ]
            - copycd.wmv
            - mdlib.wmv
            - nuskin.wmv
            - rtuner.wmv
            - viz.wmv

Zapoznaj się z powyższym kodem, a dokładnie z procedurą SearchFiles - w niej jest zaimplementowane rekurencyjne wyszukiwanie plików, reszta służy do wyświetlania drzewa wyników w konsoli;

To nie gotowiec - musisz go przystosować do własnych wymagań, przez co kodu nie skopiujesz i nie wkleisz u siebie; Aby go wykorzystać musisz go zrozumieć; Kod procedury wyszukującej jest bardzo podobny do Twojego, jednak jest w nim pewien szczegół, dzięki któremu algorytm działa poprawnie;

W załączniku zamieszczam źródła - być może komuś się kiedyś przyda.

0

zrozumiałem, poprawiłem i działa. dzięki.

0
furious programming napisał(a):
  { extract last directory name }
  function ExtractDirName(const APath: AnsiString): AnsiString;
  var
    iPathLen, I: Word;
  begin
    iPathLen := Length(APath);

    for I := Pred(iPathLen) downto 1 do
      if APath[I] = '\' then
      begin
        Result := Copy(APath, I + 1, iPathLen - I - 1);
        Exit;
      end;
  end;

A co jeśli

APath[Length(APath)]<>'\'

?

Ja robię to trochę prościej :)

  function ExtractDirName(const APath:string):string;
  begin
    Result:=ExtractFileName(ExcludeTrailingPathDelimiter(APath));
  end;

z tym, że jeśli APath nie zawiera '' to otrzymamy różne wyniki.

0

@pelsta - nie będzie inny niż \ - sprawdź stałe ROOT_PATH i DIR_NAME :]

Było już późno i wolałem napisać ręczne wyciąganie nazwy żeby czegoś nie pomylić, a nie wpadłem na nic lepszego; Twoja propozycja jest oczywiście bezpieczniejsza, gdy zapomni się przy wywołaniu procedury SearchFiles dodać na koniec znak \;

Choć równie dobrze można przy wywołaniu dodać ten znak:

SearchFiles(iTabSize, IncludeTrailingPathDelimiter(ROOT_PATH + DIR_NAME), FILTER);

i też będzie poprawnie; Ale tak jak napisałem - funkcja ExtractDirName pobiera nazwę katalogu potrzebnego jedynie do wyświetlenia drzewa i dla pytacza nie jest ważna.

1 użytkowników online, w tym zalogowanych: 0, gości: 1