4

拡張子が .cbr または .cbz のすべてのファイルを検索しようとしています。

マスクを *.cb に設定すると?

*.cbproj ファイルが見つかります。.cbr および .cbz ファイルのみを検出するようにマスクを設定するにはどうすればよいですか?

ここに私が使用しているコードがあります。

2 つの編集ボックスがあります。EDIT1 は検索する場所、EDIT2 はマスクを置く場所です。見つかったものを表示するリストボックスと検索ボタン。

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

スペース

    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.
4

2 に答える 2

7

最も簡単な方法はExtractFileExt、現在のファイル名に対して を使用し、目的の拡張子のいずれかに一致するかどうかを確認することです。

FileSearchこれは、あなたがやろうとしていることを正確に行うルーチンの完全に書き直されたバージョンです(とにかく、あなたの質問によると):

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;

複数の拡張機能をマスクとして使用することを示唆する他の回答*.cbr;*.cbzは (原則的には) 機能するはずですが、苦い経験から、Delphi のメソッドFindFirstFindNextメソッドはマスク内の複数の拡張機能を受け入れない傾向があることに気付きました!

私が提供したコードは、あなたのニーズに合わせてうまく動作するはずですので、お楽しみください!

UPDATED : 実行時にマスクで複数の拡張機能を動的に使用できるようにします (この回答に対する OP の最初のコメントで示されています)。

私たちがやろうとしていることはString、あなたのTEditコントロールから を取り (これStringはあなたが期待するように 1 つまたは複数のファイル拡張子です)、 を に「分解」Stringし、Array各ファイルを の各拡張子と照合しますArray

それよりも複雑に聞こえます:

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;

このコードには、.などでFMask区切られた個々のマスク拡張子が入力されます。;.CBR;.CBZ

このメソッドはワイルドカード文字やその他の Regex マジックを受け入れないことに注意してください。ただし、必要に応じて変更できます。

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;

指定されたファイルが定義済みの拡張子のいずれかと一致するかどうかを判断する関数が必要です。

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;

変更されたFileSearch手順は次のとおりです。

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;

最後に、検索を開始する方法は次のとおりです。

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

WhereedMaskは質問で として定義され、質問Edit2edPathは として定義されていますEdit1。このメソッドはワイルドカードやその他の特殊文字の使用をサポートしていないため、次のようにするedMask.Text必要があることに注意してください。.CBR;.CBZ

Delphi の Regex ライブラリを使用すると、このメソッドを簡単に変更して、想像できるすべての式のケースをサポートできます。

于 2012-09-29T13:58:52.600 に答える
3

マスクを交換するというドーリンの提案*.cbr;*.cbzはうまくいくはずです。つまり、cbproj とは一致しなくなります。ただし、cbzy や、cbr または cbz で始まるその他の拡張子には引き続き一致します。これは、FindFirst/FindNext がファイル名の長い形式と従来の短い形式 (8.3) の両方に一致するためです。そのため、短い形式には常に、cbproj が cbp に短縮された部分が切り詰められた拡張子が含まれるため、cb? と一致します。

これは、代わりに FindFirstEx を使用することで回避できるはずですが、これには検索機能を少し書き直す必要があり、実際には機能しませんでした。代わりに、 MatchesMask関数を使用してすべての一致を再確認しました。

于 2012-09-27T20:05:05.050 に答える