動作環境
C++ Builder XE4
ファイル探索の問題
- 下層にたくさんのフォルダがあるフォルダで、ファイル探索をすると処理が返るまで時間がかかる
これを回避するため、「フォルダ階層数」に上限を設けた探索を検討する。
処理概要
- ファイルを探索する
- linuxコマンドfindでの
-maxdepth
相当機能をC++ Builderでのファイル探索で実装
ファイル、フォルダ構造
ファイル、フォルダ構図のマインドマップ
https://atlas.mindmup.com/yasokada/_181211/index.html
下記は、上記の画像
フォームデザイン
実装
Unit1.h
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include "cspin.h"
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE で管理されるコンポーネント
TMemo *Memo1;
TLabel *Label1;
TButton *B_search;
TEdit *E_depth;
void __fastcall B_searchClick(TObject *Sender);
private: // ユーザー宣言
String __fastcall findFileInDir_maxdepthOf(String baseDir, String filePattern, int maxdepth);
public: // ユーザー宣言
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
Unit1.cpp
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include <IOUtils.hpp>
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "cspin"
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Memo1->Lines->Clear();
E_depth->Text = L"1";
}
//---------------------------------------------------------------------------
String __fastcall TForm1::findFileInDir_maxdepthOf(String baseDir, String filePattern, int maxdepth)
{
// 同じファイルが複数のフォルダにある場合、上位のフォルダのファイルが探索にひっかかる設計
//
// 1. ファイルの探索
TSearchOption filOpt = TSearchOption::soTopDirectoryOnly;
TStringDynArray fileList = TDirectory::GetFiles(baseDir, filePattern, filOpt);
if (fileList.Length > 0) {
return fileList[0];
}
if (maxdepth <= 1) {
return L""; // not found
}
// 2. フォルダの探査
TStringDynArray dirList;
TSearchOption dirOpt = TSearchOption::soTopDirectoryOnly;
dirList = TDirectory::GetDirectories(baseDir, L"*", dirOpt);
for(int idx=0; idx < dirList.Length; idx++) {
String res = findFileInDir_maxdepthOf(dirList[idx], filePattern, (maxdepth-1));
if (res.Length() > 0) {
return res;
}
}
return L""; // not found
}
void __fastcall TForm1::B_searchClick(TObject *Sender)
{
// 実行ファイル.exeがあるフォルダをベースとする
String baseDir = ExtractFileDir(Application->ExeName);
String filPtrn = L"*.csv"; // ファイル名パターン
int depth = E_depth->Text.ToInt();
String res = findFileInDir_maxdepthOf(baseDir, filPtrn, depth);
if (res.Length() == 0) {
res = L"[NOT FOUND]";
}
String msg = L"depth=" + IntToStr(depth) + L":" + res;
Memo1->Lines->Add(msg);
}
//---------------------------------------------------------------------------
動作例
備考
- 同じファイルが複数フォルダにある場合、上位フォルダのファイルが探索にひかっかる
- 下層フォルダにあるファイルが探索にひっかかってほしい場合は、探索方法の変更が必要