C++17から導入されたstd::filesystemライブラリを使ってみようの1
ここに分かりやすい解説とサンプルソースがあるので、参考にすると大吉。
directory_iteratorの例
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;
int main() {
// 走査対象のパスを指定(カレントディレクトリ ".")
fs::path target_path = ".";
try {
// directory_iteratorを使用してディレクトリ内を走査
for (const fs::directory_entry& entry : fs::directory_iterator(target_path)) {
// entry.path() でフルパスを取得し、filename() でファイル名のみを抽出
std::cout << entry.path().filename() << std::endl;
}
} catch (const fs::filesystem_error& e) {
// ディレクトリが存在しない場合などのエラー処理
std::cerr << "エラーが発生しました: " << e.what() << std::endl;
}
return 0;
}動かして見よう。

ここで、何もないところで得意の右クリック。

中程の”Open Git Bash here”を選択。

漢字コードを合わせておこう。上記のタイトルバーを右クリックして、

Options->Textを選んで以下のように、

“Apply”を選択。で”Save”。
$ bcc32c test1.cpp
Embarcadero C++ 7.70 for Win32 Copyright (c) 2012-2024 Embarcadero Technologies, Inc.
test1.cpp:
Turbo Incremental Link 6.99 Copyright (c) 1997-2024 Embarcadero Technologies, Inc.
jakeb@Orbit-11 MINGW64 ~/OneDrive/Documents/Embarcadero/Studio/Projects/directory_iterator_test
$ ./test1
directory1
recur.cpp
recur.exe
recur.tds
test1.cpp
test1.exe
test1.tds
動いてますね。
recursive_directory_iteratorの例
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;
int main() {
fs::path p = ".";
std::cout << "プロジェクト内の全ファイルをリストアップします:" << std::endl;
// 再帰的なイテレータを使用
for (const auto& entry : fs::recursive_directory_iterator(p)) {
// 現在の階層(深さ)を取得
auto depth = fs::recursive_directory_iterator(p).depth(); // 注意:これは別の方法で取得が必要
// entry自体から深さを知るには、イテレータを明示的に定義する
}
// 正しい深さの取得方法を含むループ
fs::recursive_directory_iterator iter(p);
fs::recursive_directory_iterator end;
while (iter != end) {
// インデントで階層を表現
for (int i = 0; i < iter.depth(); ++i) std::cout << " ";
std::cout << "-> " << iter->path().filename() << std::endl;
// 次の要素へ
++iter;
}
return 0;
}
$ bcc32c recur.cpp
Embarcadero C++ 7.70 for Win32 Copyright (c) 2012-2024 Embarcadero Technologies, Inc.
recur.cpp:
Turbo Incremental Link 6.99 Copyright (c) 1997-2024 Embarcadero Technologies, Inc.
jakeb@Orbit-11 MINGW64 ~/OneDrive/Documents/Embarcadero/Studio/Projects/directory_iterator_test
$ ./recur
プロジェクト内の全ファイルをリストアップします:
-> directory1
-> alt..txt
-> recur.cpp
-> recur.exe
-> recur.tds
-> test1.cpp
-> test1.exe
-> test1.tds
再帰的にスキャンできていることが確認できた。実は既出のscan projectプログラムで既に使っているテクニックである。基本的には、C++ Builder CEないしDelphi界隈のString(UnicodeString)とstd::stringの相互変換が必要になることに注意が必要だ。
WindowsのファイルエクスプローラーへのファイルないしフォルダーのDrag and Dropを処理するために、以前の記事の、
を使う。FMXのプログラムを新規作成し、フォームは、

とりあえず、TMemoだけおいて、Unit1.hは、
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <FMX.Controls.hpp>
#include <FMX.Forms.hpp>
#include <FMX.Controls.Presentation.hpp>
#include <FMX.Memo.hpp>
#include <FMX.Memo.Types.hpp>
#include <FMX.ScrollBox.hpp>
#include <FMX.Types.hpp>
#include <FMX.StdCtrls.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE で管理されるコンポーネント
TMemo *Memo1;
private: // ユーザー宣言
public: // ユーザー宣言
__fastcall TForm1(TComponent* Owner);
virtual void __fastcall DragDrop(const Fmx::Types::TDragObject &Data, const System::Types::TPointF &Point);
virtual void __fastcall DragOver(const Fmx::Types::TDragObject &Data, const System::Types::TPointF &Point, Fmx::Types::TDragOperation &Operation);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endifUnit1.cppは、directory_iteratorを使って、
#include <fmx.h>
#pragma hdrstop
#include <System.SysUtils.hpp>
#include <filesystem>
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.fmx"
namespace fs = std::filesystem;
TForm1 *Form1;
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Memo1->Lines->Add("working....");
}
void DigDirectory(String path)
{
fs::path target_path = path.c_str();
try {
// directory_iteratorを使用してディレクトリ内を走査
for (const fs::directory_entry& entry : fs::directory_iterator(target_path)) {
// entry.path() でフルパスを取得し、filename() でファイル名のみを抽出
//std::cout << entry.path().filename() << std::endl;
//Form1->Memo1->Lines->Add( path + "\\" + entry.path().filename().c_str());
Form1->Memo1->Lines->Add(entry.path().c_str());
}
} catch (const fs::filesystem_error& e) {
// ディレクトリが存在しない場合などのエラー処理
//std::cerr << "エラーが発生しました: " << e.what() << std::endl;
ShowMessage("error");
}
}
void __fastcall TForm1::DragDrop(const Fmx::Types::TDragObject &Data, const System::Types::TPointF &Point)
{
TForm::DragDrop(Data,Point);
for( int i = 0 ; i < Data.Files.Length ; i ++ ){
if(DirectoryExists(Data.Files[i]))
DigDirectory(Data.Files[i]);
else
Memo1->Lines->Add(Data.Files[i]);
}
}
void __fastcall TForm1::DragOver(const Fmx::Types::TDragObject &Data, const System::Types::TPointF &Point, Fmx::Types::TDragOperation &Operation)
{
TForm::DragOver(Data,Point,Operation);
Operation = TDragOperation::Copy;
}
//---------------------------------------------------------------------------Drag and Dropしたものの中にDirectoryがあれば、その中もリストする。そこにさらにDirectoryが在っても名前だけ記録する。

さらに、

の場合、

をDrag and Dropすると、

となる。さて、実際の動作はタイムスタンプの修正を行うのであるが、それは次回以降で。



コメント