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