C++Builderで、ディスクおよびディレクトリの管理に使用するルーチン(関数)について説明します。
使用方法
一部、使用方法についても説明します。
ディレクトリ名(フォルダ名)、ファイル名の検索
TDirectoryクラスには、以下のディレクトリ名(フォルダ名)やファイル名を検索するルーティン(メソッド)があります。再帰処理を自分で処理する必要があった階層以下の検索も、これらのメソッドで検索が可能です。
メソッド | 説明 |
---|---|
GetDirectories | 指定のディレクトリ内のサブディレクトリのリストを返します。 |
GetFiles | 指定のディレクトリ内のファイルのリストを返します。 |
GetFileSystemEntries | 指定のディレクトリ内のファイルとサブディレクトリのリストを返します。 |
これからのメソッドには、以下の 3 つの形式があります。
- 1番目の形式は、ファイルを列挙したいディレクトリのパスのみを受理します。
- 2番目の形式には、ファイル名に一致する検索パターンが含まれています。
- 3番目の形式には、列挙する際に再帰モードを使用するかどうかを指定するオプションが含まれています。
どの形式も、結果をフィルタリングするために使われる TFilterPredicate オプション パラメータを受理します。
サンプルコード1
DirectoriesAndFilesEnumeraion (C++) で、公開されているサンプルコードです。
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TStringDynArray list;
TSearchOption searchOption;
/* Select the search option */
if (cbDoRecursive->Checked)
searchOption = TSearchOption::soAllDirectories;
else
searchOption = TSearchOption::soTopDirectoryOnly;
try
{
/* For all entries use GetFileSystemEntries method */
if (cbIncludeDirectories->Checked && cbIncludeFiles->Checked)
list = TDirectory::GetFileSystemEntries(edtPath->Text, searchOption, NULL);
/* For directories use GetDirectories method */
if (cbIncludeDirectories->Checked && !cbIncludeFiles->Checked)
list = TDirectory::GetDirectories(edtPath->Text, edtFileMask->Text, searchOption);
/* For files use GetFiles method */
if (!cbIncludeDirectories->Checked && cbIncludeFiles->Checked)
list = TDirectory::GetFiles(edtPath->Text, edtFileMask->Text, searchOption);
}
catch (...)
{
/* Catch the possible exceptions */
MessageDlg("Incorrect path or search mask", mtError, TMsgDlgButtons() << mbOK, 0);
return;
}
/* Populate the memo with the results */
Memo1->Clear();
for (int i = 0; i < list.Length; i++)
Memo1->Lines->Add(list[i]);
}
TSearchOption
TSearchOption は、TDirectory の一部のメソッドで、スキャン ルーチンが最上位ディレクトリのみ対象とするか他のすべてのディレクトリを再帰的に対象とするかを指定するのに使用されます。TSearchOption の取り得る値は以下のとおりです。
値 | 意味 |
---|---|
soTopDirectoryOnly | 最上位のファイルまたはディレクトリのみスキャンします。 |
soAllDirectories | 最上位のディレクトリまたはファイルを起点として、すべてのディレクトリやファイルを再帰的にスキャンします。 |
サンプルコード2
上記の2番目の形式を使用したGetFilesのサンプルコードです。検索パターンに一致したファイルを検索します。
また、soAllDirectoriesを指定して、階層以下の検索も行います。自分で、再帰処理をする必要がないので、非常に簡単に検索が可能ですね。
// ----------------------------------------------------------------------------
/**
* @brief ファイルの検索
*
* @param[in,out] TStrings* FileList : 検索するフォルダのリスト
* @param[in,out] TStrings* ImgFiles : 検索したファイルを格納するストリングリスト
*
* @return なし (none)
*/
// ----------------------------------------------------------------------------
void __fastcall TDesktopWindow::SearchFile(TStrings *FileList, TStrings *ImgFiles)
{
int formatno = 9;
String path;
String SearchPattern;
TSearchOption searchOption = TSearchOption::soAllDirectories; // soTopDirectoryOnly
// soTopDirectoryOnly 最上位のファイルまたはディレクトリのみスキャンします。
// soAllDirectories 最上位のディレクトリまたはファイルを起点として、すべてのディレクトリやファイルを再帰的にスキャンします。
for(int i=0;i<FileList->Count;i++)
{
for(int j=0;j<formatno;j++)
{
path = FileList->Strings[i];
// if(*fname.LastChar() != L'\\') { fname += "\\"; }
switch(j)
{
case 0: SearchPattern = "*.jp*"; break;
case 1: SearchPattern = "*.bmp"; break;
case 2: SearchPattern = "*.dib"; break;
case 3: SearchPattern = "*.gif"; break; // strcat(fName, "*.pcd"); break;
case 4: SearchPattern = "*.png"; break;
case 5: SearchPattern = "*.webp"; break;
case 6: SearchPattern = "*.ico*"; break;
case 7: SearchPattern = "*.tif*"; break;
case 8: SearchPattern = "*.heic"; break;
default: break;
}
TStringDynArray files = TDirectory::GetFiles(path, SearchPattern, searchOption);
for (int i = 0; i < files.Length; ++i)
{
ImgFiles->Add(files[i]);
}
}
}
}
TFilterPredicate オプションを使用したサンプル
Clang 拡張 C++ コンパイラを使用して、Delphi API が Delphi 無名メソッドを想定するところでは、ラムダ式を使用して、TFilterPredicate オプションを実装することができます。
C++ における無名メソッド型の処理に、以下のサンプルコードが公開あれています。
#include <System.hpp>
#include <System.IOUtils.hpp>
#include <iostream>
int main()
{
String ext(".cpp");
TStringDynArray files = TDirectory::GetFiles(TDirectory::GetCurrentDirectory(),
[ext](const String Path, const System::Sysutils::TSearchRec &SearchRec) -> bool
{
return ExtractFileExt(SearchRec.Name) == ext;
});
std::cout << "Found " << files.Length
<< " files with ext: '" << AnsiString(ext).c_str() << "'\n";
for (int i=0; i<files.Length; ++i)
std::cout << AnsiString(files[i]).c_str() << std::endl;
}
上記のコードを修正して、「サンプルコード2」と同じ処理を実装してみました。
void __fastcall TDesktopWindow::SearchFile(TStrings *FileList, TStrings *ImgFiles)
{
int formatno = 9;
String path;
String SearchPattern = L"*";
TSearchOption searchOption = TSearchOption::soAllDirectories; // soTopDirectoryOnly
// soTopDirectoryOnly 最上位のファイルまたはディレクトリのみスキャンします。
// soAllDirectories 最上位のディレクトリまたはファイルを起点として、すべてのディレクトリやファイルを再帰的にスキャンします。
for(int i=0;i<FileList->Count;i++)
{
path = FileList->Strings[i];
TStringDynArray files = TDirectory::GetFiles(path, SearchPattern, searchOption,
[path](const String path, const System::Sysutils::TSearchRec &SearchRec) -> bool
{
// return ExtractFileExt(SearchRec.Name) == path;
bool ret = false;
String FileExt = TPath::GetExtension(SearchRec.Name); // String FileExt = ExtractFileExt(FileName);
FileExt = UpperCase(FileExt);
if( (FileExt.Compare(".BMP") == 0) || (FileExt.Compare(".DIB") == 0) )
{
ret = true;
} else if(FileExt.Compare(_TEXT(".GIF")) == 0) {
ret = true;
} else if(FileExt.Compare(_TEXT(".PNG")) == 0) {
ret = true;
} else if( FileExt.Pos(L".JP") != 0) {
ret = true;
} else if(FileExt.Compare(_TEXT(".WEBP")) == 0) {
ret = true;
} else if(FileExt.Compare(_TEXT(".ICO")) == 0) {
ret = true;
} else if( FileExt.Pos(L".TIF") != 0) {
ret = true;
} else if( FileExt.CompareIC(L".HEIC") == 0) { // 2024/02/24
ret = true;
} else {
ret = false;
}
return ret;
});
// TStringDynArray files = TDirectory::GetFiles(path, searchOption, FilterPredicate);
for (int i = 0; i < files.Length; ++i)
{
ImgFiles->Add(files[i]);
}
}
}
ForceDirectories
ForceDirectories は、Dir で指定された新しいディレクトリを作成します。これは、完全修飾パス名でなければなりません。 パスに指定されたディレクトリが存在しない場合、ForceDirectories はその作成を試みます。この関数では、複数の階層のディレクトリを作成することができ便利です。
ForceDirectories は、必要なディレクトリをすべて作成できた場合には true を、必要なディレクトリが 1 つでもできなかった場合には、false を返します。
以下は、実行ファイルの置いてあるフォルダの下に、”data”というフォルダを作成します。
String path = TPath::GetDirectoryName(Application->ExeName);
path = IncludeTrailingPathDelimiter(path) + "data";
ForceDirectories(path);
ディスクおよびディレクトリの管理用のルーティン一覧
以下、ディスクおよびディレクトリの管理に使用される全関数の一覧です。
System
Systemで定義されている関数群です。
ルーチン | 説明 |
---|---|
System.ChDir | 現在のディレクトリを変更します。 |
System.GetDir | 現在のディレクトリを返します。 |
System.IOResult | 最後に実行された I/O 操作のステータスを返します。 |
System.MkDir | 新しいサブディレクトリを作成します。 |
System.RmDir | 空のサブディレクトリを削除します。 |
System.SysUtils
System.SysUtilsで定義されている関数群です。
ルーチン | 説明 |
---|---|
System.SysUtils.CreateDir | 新しいディレクトリを作成します。 |
System.SysUtils.DeleteFile | ファイルをディスクから削除します。ファイル名が ANSI 文字列であるファイルを削除します。 |
System.SysUtils.DiskFree | 指定されたドライブの使用可能バイト数を返します。 |
System.SysUtils.DiskSize | 指定されたドライブのサイズをバイト単位で返します。 |
System.SysUtils.FileSearch | 指定のディレクトリ パス内でファイルを探します。 |
System.SysUtils.FindClose | FindFirst で割り当てられたメモリを解放します。 |
System.SysUtils.FindFirst | 指定されたファイル名と一連の属性を持つ最初のファイルを、指定されたディレクトリ内で探します。 |
System.SysUtils.FindNext | 前回の FindFirst の呼び出しで指定された名前と属性に一致する次のファイルを返します。 |
System.SysUtils.ForceDirectories | 新しいディレクトリを作成します(必要に応じて親ディレクトリも作成します)。 |
System.SysUtils.GetCurrentDir | 現在のディレクトリの名前を返します。 |
System.SysUtils.RemoveDir | 既存の空ディレクトリを削除します。 |
System.SysUtils.SetCurrentDir | 現在のディレクトリを設定します。 |
System.IOUtils.TDirectory
TDirectoryクラスです。Delphi 2010以降に追加されたようです。
ルーチン | 説明 |
---|---|
System.IOUtils.TDirectory.Copy | ディレクトリとその内容をコピーします。 |
System.IOUtils.TDirectory.CreateDirectory | 指定のパスに新しいディレクトリを作成します。 |
System.IOUtils.TDirectory.Delete | 指定のパスにあるディレクトリを削除します。 |
System.IOUtils.TDirectory.Exists | 指定のディレクトリが存在するかどうかをチェックします。 |
System.IOUtils.TDirectory.GetAttributes | ディレクトリ属性を返します。 |
System.IOUtils.TDirectory.GetCreationTime | ディレクトリの作成時刻を返します。 |
System.IOUtils.TDirectory.GetCreationTimeUtc | ディレクトリの作成時刻を UTC(Coordinated Universal Time:協定世界時)タイム ゾーンで返します。 |
System.IOUtils.TDirectory.GetCurrentDirectory | 現在の作業ディレクトリを返します。 |
System.IOUtils.TDirectory.GetDirectories | 指定のディレクトリ内のサブディレクトリのリストを返します。 |
System.IOUtils.TDirectory.GetDirectoryRoot | 指定のパスのルート ディレクトリを返します。 |
System.IOUtils.TDirectory.GetFiles | 指定のディレクトリ内のファイルのリストを返します。 |
System.IOUtils.TDirectory.GetFileSystemEntries | 指定のディレクトリ内のファイルとサブディレクトリのリストを返します。 |
System.IOUtils.TDirectory.GetLastAccessTime | ディレクトリの最終アクセス時刻を返します。 |
System.IOUtils.TDirectory.GetLastAccessTimeUtc | ディレクトリの最終アクセス時刻を UTC(Coordinated Universal Time:協定世界時)タイム ゾーンで返します。 |
System.IOUtils.TDirectory.GetLastWriteTime | ディレクトリの最終書き込み時刻を返します。 |
System.IOUtils.TDirectory.GetLastWriteTimeUtc | ディレクトリの最終書き込み時刻を UTC(Coordinated Universal Time:協定世界時)タイム ゾーンで返します。 |
System.IOUtils.TDirectory.GetLogicalDrives | このコンピュータ上に存在するすべての論理ドライブのリストを返します。 |
System.IOUtils.TDirectory.GetParent | あるディレクトリの親ディレクトリを返します。 |
System.IOUtils.TDirectory.IsEmpty | 指定のディレクトリが空かどうかをチェックします。 |
System.IOUtils.TDirectory.IsRelativePath | IsRelativePath は、指定されたパスが相対パスかどうかを示します。 |
System.IOUtils.TDirectory.Move | ディレクトリとその内容を移動または名前変更します。 |
System.IOUtils.TDirectory.SetAttributes | ディレクトリ属性を設定します。 |
System.IOUtils.TDirectory.SetCreationTime | ディレクトリの作成時刻を変更します。 |
System.IOUtils.TDirectory.SetCreationTimeUtc | ディレクトリの作成時刻を変更します。 |
System.IOUtils.TDirectory.SetCurrentDirectory | 現在のディレクトリを設定します。 |
System.IOUtils.TDirectory.SetLastAccessTime | ディレクトリの最終アクセス時刻を変更します。 |
System.IOUtils.TDirectory.SetLastAccessTimeUtc | ディレクトリの最終アクセス時刻を変更します。 |
System.IOUtils.TDirectory.SetLastWriteTime | ディレクトリの最終書き込み時刻を変更します。 |
System.IOUtils.TDirectory.SetLastWriteTimeUtc | ディレクトリの最終書き込み時刻を変更します。 |
参考URL
以下、参考となるURLです。