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.