Delphi Programming / Object Pascal
サイトのトップページへ リンクのページへ ロゴマーク
[掲載 2014年07月16日] [更新 2014年07月16日] Delphi サンプルプログラム集
778_ワイルドカードでファイル名をチェック
動作確認等 Windows 7 U64(SP1) + Delphi XE(UP1) Pro
778_FileName_WildCard.zip [1,754 KB] 2014年07月16日版 (EXE 同梱)







ワイルドカードを使用したファイル名のチェック


ファイル名やディレクトリ名、パス名が、下表のような、指定したワイルドカードに一致するかをチェックするサンプルです。
TMask を使用します。TMask は少なくても Delphi 5 には実装されています。
Windows のファイル名は、Unix とは違い、大文字と小文字の区別はありません。したがって、ワイルドカードで指定する文字も大文字と小文字の区別はありません。

タイトルはファイル名となっていますが、実際には、文字列がワイルドカードに一致するかのチェックです。



ワイルドカード 説明
* 任意の長さの文字列 (長さ 0 も含まれる)
? 任意の 1 文字
[] [] 内の任意の 1 文字
- を使用して、範囲の指定も可能。例えば [A-Z] は A ~ Z のいずれかの文字
[!] ! の後の任意の文字ではない 1 文字
- を使用して、上の [] と同じように範囲の指定が可能


Delphi 2010 以降の TDirectory の GetFiles 関数では、引数で、上の表のワイルドカードが指定できます。また、望まない結果を除去する方法も用意されています。
したがって、本ページのサンプルは、

  • FindFirst と FindNext を使用してディレクトリ内のファイルを列挙する
  • 既にあるファイル名のリストから、ワイルドカードに一致するファイルだけを取り出す

場合の参考コードです。ただし、ディレクトリ内のファイルのリストの取得に、Delphi 2010 以降で使用可能な TDirectory.GetFiles を使用しています。Delphi 2009 以前の場合は、以下のリンクの記事を参考してください。

FindFirst と FindFirstFile 関数を使用したディレクトリやファイルの検索でもワイルドカードを指定できますが、上の表の [] を使用したワイルドカードは指定できません。次項以降のサンプルコードのように、取得したファイル名 (文字列) に対しての操作となります。



ワイルドカードではなく、文字列に、文字列の集合 (文字列配列) のどれかと同じであるかをチェックするには、上の参考リンクの正規表現の記事にも参考コードがありますが、StrUtils.MatchText 等の関数も利用できます。



リスト1
TDirectory.GetFiles では、引数でワイルドカードを指定できる (Delphi 2010 以降)
//=============================================================================
//  フォーム表示開始時の処理
//  デフォルトのワイルドカードを設定
//=============================================================================
procedure TForm1.FormShow(Sender: TObject);
begin
  Edit1.Text := '*.*';
end;

//=============================================================================
//  指定ディレクトリ内の、指定パターンに一致するファイル名をリスト
//  TDirectory.GetFilesの引数で、ワイルドカードを指定する
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  ADir      : String;
  FilesList : TStringDynArray;
  i         : Integer;
  FileName  : String;
begin
  ADir := ExtractFileDir(Application.ExeName);
  if FileCtrl.SelectDirectory('検索フォルダ指定', '', ADir) then begin
    Memo1.Lines.Clear;
    Memo1.Lines.BeginUpdate;

    //ファイルのリストを取得
    //指定のパターンに一致するファイル名だけを取り出す
    FilesList := TDirectory.GetFiles(ADir, Trim(Edit1.Text));
    for i := 0 to Length(FilesList) - 1 do begin
      FileName := TPath.GetFileName(FilesList[i]);
      Memo1.Lines.Add(FileName);
    end;
    Memo1.Lines.EndUpdate;
  end;
end;




01_TMask の Matches メソッドを使用したテスト


TMask の Matches メソッドを使用する例です。実行時に TMask のインスタンスを生成します。


図1
設計時画面

図2
テストに使用したファイルのリスト

下図は、実際にワイルドカードを指定してテストした結果です。


図3
全てのファイル

図4
拡張子の前が ject1 であるファイル
図5
途中に . (ドット) があるファイル
図6
先頭が A で、次が連続した 3 桁の数字のファイル
図7
途中に連続した 3 桁の数字がないファイル
図8
拡張子が .txt だけのファイル

リスト2
ワイルドカードに一致するファイル名だけをリスト
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
    procedure FormShow(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

uses Masks, FileCtrl, Types, IOUtils;

{$R *.dfm}

//=============================================================================
//  フォーム表示開始時の処理
//  デフォルトのワイルドカードを設定
//=============================================================================
procedure TForm1.FormShow(Sender: TObject);
begin
  Edit1.Text := '*.*';
end;

//=============================================================================
//  指定ディレクトリ内の、ワイルドカードに一致するファイルをリスト
//  TMaskのMatchesメソッドを使用
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  ADir         : String;
  FilesList    : TStringDynArray;
  i            : Integer;
  FileName     : String;
  FileNameMask : TMask;
begin
  ADir := ExtractFileDir(Application.ExeName);
  if FileCtrl.SelectDirectory('検索フォルダ指定', '', ADir) then begin
    Memo1.Lines.Clear;
    Memo1.Lines.BeginUpdate;

    FileNameMask := TMask.Create(Trim(Edit1.Text));
    try
      //ファイルのリストを取得
      FilesList := TDirectory.GetFiles(ADir);
      //ファイルのリストからワイルドカードに一致するファイル名だけを取り出す
      for i := 0 to Length(FilesList) - 1 do begin
        FileName := TPath.GetFileName(FilesList[i]);
        if FileNameMask.Matches(FileName) then begin
          Memo1.Lines.Add(FileName);
        end;
      end;
      Memo1.Lines.EndUpdate;
    finally
      FileNameMask.Free;
    end;
  end;
end;

end.




02_Mask.pas の MatchesMask 関数を使用したテスト


Mask.pas に実装されている MatchesMask 関数を使用する例です。
MatchesMask 関数は、内部で TMask のインスタンスを生成し、前項のサンプルで使用した Matches メソッドを実行しています。実行結果は上のサンプルと同じです。


[備考]
Delphi 2010 以前の Delphi の MatchesMask 関数は、メモリリークが発生するようです。筆者の環境の Delphi XE 以降ではメモリリークは確認されていません。
Delphi XE (Build: 15.0.3573.25335) で修正されたようです。


リスト3
ワイルドカードに一致するファイル名だけをリスト
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
    procedure FormShow(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

uses Masks, FileCtrl, Types, IOUtils;

{$R *.dfm}

//=============================================================================
//  フォーム表示開始時の処理
//  デフォルトのワイルドカードを設定
//=============================================================================
procedure TForm1.FormShow(Sender: TObject);
begin
  Edit1.Text := '*.*';
end;

//=============================================================================
//  指定ディレクトリ内の、ワイルドカードに一致するファイルをリスト
//  Masks.pasのMatchesMask関数を使用
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  ADir      : String;
  FilesList : TStringDynArray;
  i         : Integer;
  FileName  : String;
begin
  ADir := ExtractFileDir(Application.ExeName);
  if FileCtrl.SelectDirectory('検索フォルダ指定', '', ADir) then begin
    Memo1.Lines.Clear;
    Memo1.Lines.BeginUpdate;

    //ファイルのリストを取得
    FilesList := TDirectory.GetFiles(ADir);
    //ファイルのリストからワイルドカードに一致するファイル名だけを取り出す
    for i := 0 to Length(FilesList) - 1 do begin
      FileName := TPath.GetFileName(FilesList[i]);
      if Masks.MatchesMask(FileName, Trim(Edit1.Text)) then begin
        Memo1.Lines.Add(FileName);
      end;
    end;
    Memo1.Lines.EndUpdate;
  end;
end;

end.