4 Stimmen

Dateimaskierung in Delphi

Ich versuche alle Dateien zu finden, die die Endung .cbr oder .cbz haben

Wenn ich meine Maske auf *.cb?

es findet *.cbproj-Dateien. Wie kann ich die Maske so einstellen, dass nur .cbr- und .cbz-Dateien gefunden werden?

Hier ist der Code, den ich verwende.

Ich habe zwei Eingabefelder: EDIT1 ist der Ort, an dem ich suche, EDIT2 ist der Ort, an dem ich meine Maske einfüge. Ein Listenfeld, um anzuzeigen, was gefunden wurde, und eine Schaltfläche Suchen.

edit1 := c:\
edit2 := mask (*.cb?)

Raum

    procedure TFAutoSearch.FileSearch(const PathName, FileName : string; const InDir : boolean);
var Rec  : TSearchRec;
    Path : string;
begin
Path := IncludeTrailingBackslash(PathName);
if FindFirst(Path + FileName, faAnyFile - faDirectory, Rec) = 0 then
 try
   repeat
     ListBox1.Items.Add(Path + Rec.Name);
   until FindNext(Rec) <> 0;
 finally
   FindClose(Rec);
 end;

If not InDir then Exit;

if FindFirst(Path + '*.*', faDirectory, Rec) = 0 then
 try
   repeat
    if ((Rec.Attr and faDirectory) <> 0)  and (Rec.Name<>'.') and (Rec.Name<>'..') then
     FileSearch(Path + Rec.Name, FileName, True);
   until FindNext(Rec) <> 0;
 finally
   FindClose(Rec);
 end;
end; //procedure FileSearch

procedure TFAutoSearch.Button1Click(Sender: TObject);
begin
  FileSearch(Edit1.Text, Edit2.Text, CheckBox1.State in [cbChecked]);
end;

end.

7voto

LaKraven Punkte 5746

Der einfachste Weg ist die Verwendung von ExtractFileExt mit dem aktuellen Dateinamen vergleichen und prüfen, ob er mit einer der gewünschten Erweiterungen übereinstimmt.

Hier ist eine vollständig umgeschriebene Version Ihrer FileSearch Routine, die genau das tut, was Sie zu tun versuchen (laut Ihrer Frage jedenfalls):

procedure TFAutoSearch.FileSearch(const ARoot: String);
var
  LExt, LRoot: String;
  LRec: TSearchRec;
begin
  LRoot := IncludeTrailingPathDelimiter(ARoot);
  if FindFirst(LRoot + '*.*', faAnyFile, LRec) = 0 then
  begin
    try
      repeat
        if (LRec.Attr and faDirectory <> 0) and (LRec.Name <> '.') and (LRec.Name <> '..') then
          FileSearch(LRoot + LRec.Name)
        else
        begin
          LExt := UpperCase(ExtractFileExt(LRoot + LRec.Name));
          if (LExt = '.CBR') or (LExt = '.CBZ') then
            ListBox1.Items.Add(LRoot + LRec.Name);
        end;
      until (FindNext(LRec) <> 0);
    finally
      FindClose(LRec);
    end;
  end;
end;

Während die andere Antwort die Verwendung mehrerer Durchwahlen als Maske vorschlägt *.cbr;*.cbz (prinzipiell) funktionieren sollte, habe ich aus bitterer Erfahrung festgestellt, dass die FindFirst y FindNext Methoden in Delphi neigen dazu, mehrere Erweiterungen in einer Maske nicht zu akzeptieren!

Der Code, den ich zur Verfügung gestellt habe, sollte für Ihre Bedürfnisse gut funktionieren, also viel Spaß!

AKTUALISIERT : Um die Verwendung von mehreren Erweiterungen in einer Maske dynamisch zur Laufzeit zu ermöglichen (wie im ersten Kommentar des Auftraggebers zu dieser Antwort angedeutet).

Was wir tun werden, ist eine String von Ihrem TEdit Kontrolle (diese String ist eine oder mehrere Dateierweiterungen, wie Sie es erwarten würden), "Explode" die String in eine Array und gleichen jede Datei mit jeder Erweiterung in der Array .

Das klingt komplizierter als es ist:

type
  TStringArray = Array of String; // String Dynamic Array type...

// Now let's provide a "Mask Container" inside the containing class...
  TFAutoSearch = class(TForm)
    // Normal stuff in here
  private
    FMask: TStringArray; // Our "Mask Container"
  end;

Dieser Code füllt FMask mit jeder einzelnen Maskenerweiterung getrennt durch ein ; wie zum Beispiel .CBR;.CBZ .

Beachten Sie, dass diese Methode keine Wildcard-Zeichen oder andere Regex-Magie akzeptiert, aber Sie können sie nach Bedarf ändern!

procedure TFAutoSearch.ExplodeMask(const AValue: String);
var
  LTempVal: String;
  I, LPos: Integer;
begin
  LTempVal := AValue;
  I := 0;
  while Length(LTempVal) > 0 do
  begin
    Inc(I);
    SetLength(FMask, I);
    LPos := Pos(';', LTempVal);

    if (LPos > 0) then
    begin
      FMask[I - 1] := UpperCase(Copy(LTempVal, 0, LPos - 1));
      LTempVal := Copy(LTempVal, LPos +  1, Length(LTempVal));
    end
    else
    begin
      FMask[I - 1] := UpperCase(LTempVal);
      LTempVal := EmptyStr;
    end;
  end;
end;

Wir brauchen nun eine Funktion, die feststellt, ob die angegebene Datei einer der definierten Erweiterungen entspricht:

function TFAutoSearch.MatchMask(const AFileName: String): Boolean;
var
  I: Integer;
  LExt: String;
begin
  Result := False;
  LExt := UpperCase(ExtractFileExt(LExt));
  for I := Low(FMask) to High(FMask) do
    if (LExt = FMask[I]) then
    begin
      Result := True;
      Break;
    end;
end;

Hier ist die geänderte Version FileSearch Verfahren:

procedure TFAutoSearch.FileSearch(const ARoot: String);
var
  LRoot: String;
  LRec: TSearchRec;
begin
  LRoot := IncludeTrailingPathDelimiter(ARoot);
  if FindFirst(LRoot + '*.*', faAnyFile, LRec) = 0 then
  begin
    try
      repeat
        if (LRec.Attr and faDirectory <> 0) and (LRec.Name <> '.') and (LRec.Name <> '..') then
          FileSearch(LRoot + LRec.Name)
        else
        begin
          if (MatchMask(LRoot + LRec.Name)) then
            ListBox1.Items.Add(LRoot + LRec.Name);
        end;
      until (FindNext(LRec) <> 0);
    finally
      FindClose(LRec);
    end;
  end;
end;

Und schließlich: So leiten Sie Ihre Suche ein:

procedure TFAutoSearch.btnSearchClick(Sender: TObject);
begin
  ExplodeMask(edMask.Text);
  FileSearch(edPath.Text);
end;

Wo edMask ist in Ihrer Frage definiert als Edit2 y edPath ist in Ihrer Frage definiert als Edit1 . Denken Sie daran, dass diese Methode die Verwendung von Platzhaltern oder anderen Sonderzeichen nicht unterstützt, also edMask.Text sollte etwa so lauten .CBR;.CBZ

Wenn Sie die Regex-Bibliothek für Delphi verwenden, können Sie diese Methode leicht modifizieren, um alle denkbaren Expression Cases zu unterstützen!

3voto

boileau Punkte 807

Dorins Vorschlag, die Maske zu ersetzen durch *.cbr;*.cbz sollte funktionieren. Das heißt, es wird nicht mehr mit cbproj übereinstimmen. Es würde jedoch immer noch auf cbzy oder jede andere Erweiterung passen, die mit cbr oder cbz beginnt. Der Grund dafür ist, dass FindFirst/FindNext sowohl die Langform als auch die veralteten Kurzformen (8.3) von Dateinamen abgleichen. Die Kurzformen werden also immer verkürzte Erweiterungen haben, wobei cbproj zu cbp verkürzt wird und daher zu cb? passt.

Dies soll durch die Verwendung von FindFirstEx vermeidbar sein, aber dies erfordert eine kleine Umschreibung Ihrer Suchfunktion und hat bei mir nicht funktioniert. Also habe ich stattdessen einfach alle Übereinstimmungen mit der ÜbereinstimmungenMaske Funktion.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X