MFCなどでファイル走査などのプログラミングを行っていると、D&D(ドラッグアンドドロップ)されたフォルダー内の全ファイル(サブフォルダー含め)に何か処理を行い、同じような階層を維持したまま別のフォルダーに写し取りたい場合があります。
- 以下のフォルダーに格納されている全ファイル(サブフォルダー含め)にXXX処理を行う。
“C:\\Users\\user\\Documents\\workspace\\” - 処理が終われば以下のフォルダーに出力する。
尚、”user”以下のフォルダー構成は維持する。
“C:\\image\\”
この場合、「”C:\\image\\user”があるか?」、「なければ作る」といった処理が必要になります。
フォルダー構成がコピーできればファイルごとの比較などもしやすくなります。
サンプルプログラムを見ながら実装してみましょう。
どんなソースコードになる?
もっとスマートに記述できるような気もするのですが…。
あまり時間もかけられない関係上、以下のような内容でフルパスからフォルダー構成をコピーできます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
#include "afxcoll.h" // CString #include "wchar.h" // _wmkdir int main() { // 任意のファイルのフルパス。実務上は処理対象のファイルパス。 CString fullpath = "C:\\Users\\user\\Documents\\workspace\\sample.bmp"; // どこからフォルダー構成をコピーするか。 CString root = "user"; // 出力先 CString output = _T("C:\\image\\") + fullpath.Right(_tcsclen(fullpath) - fullpath.Find(root)); int nCount = 0; while(true) { // 出力先パスから各フォルダーの出現位置を取得 nCount = output.Find(_T("\\"), nCount); // 全てのフォルダーを確認したらループ脱出 if (-1 == nCount) break; // 各フォルダーのパス(C:, C:\\image, C:\\image\\user...)を取得・作成する。 // 失敗した(=作成できなかった)場合はエラーコードが返るので必要なら取得します。 _wmkdir(output.Left(nCount)); // 同じフォルダーを取得しないようカウンタをインクリメント nCount++; } } |
サンプルコードでは「Win32 コンソールアプリケーション」で確認していますが、CStringなどで確認できたのでMFCでも問題なく実行できるはずです。
ボタンのイベントハンドラーにコーディングすれば簡単にテストできるかと思います。
処理内容の解説
フォルダーの出現位置取得
上記コード、18行目の部分です。
1 2 |
// フルパスから各フォルダーの出現位置を取得 nCount = output.Find(_T("\\"), nCount); |
CString::Find関数は、引数で指定した文字(文字列)が一致した場所を返す関数です。
関連リンク:CStringT::Find
第二引数のnCountは「検索を開始する文字列のインデックス」を指定します。
ループの最後でインクリメントしているのはこの検索開始位置をずらすためです。
また戻り値で-1が返ってきた場合(=見つからなかった)、ループから脱出し処理を終了します。
各フォルダーのパスを取得
1 2 3 |
// 各フォルダーのパス(C:, C:\\Users, C:\\Users\\user...)を取得・作成する。 // 失敗した(=作成できなかった)場合はエラーコードが返るので必要なら取得します。 _wmkdir(output.Left(nCount)); |
フォルダーを作成する関数、_mkdir(_wmkdir)関数は引数に「作成するフォルダのパス」を指定する必要があります。
そのため、”C:\\image\\user\\Documents”であれば、
- “C:\\”
- “C:\\image”
- “C:\\image\\user”
- “C:\\image\\user\\Documents”
の4パターンが必要になります。
(「C:\\」や「C:\\image」などは冗長な気もしますが…。)
引数には「CString::Left関数」と「フォルダーの出現位置」から上記4パターンを取得しています。
関連リンク:CStringT::Left
今回は戻り値をチェックせず、作れなかった場合の処理は記述していません。
作れなかった場合には、
- 既にフォルダが存在する
- 指定されたフォルダーに到達できない(「C:」がないなど)
などがあります。
エラー処理が必要な場合は適宜追加してください。
まとめ
作成しようと思ったのは、一つのフォルダーをMFCにD&Dして、そのフォルダーに含まれる全ての画像ファイルを変換する作業からでした。
サブフォルダーもかなりあり、フォルダー構成もまるごとコピーできれば比較などもしやすいためでした。
先述したようにもっとスマートに、エレガントに記述できるような気もするのですが、現状ではこの操作で動かしてみようと思います。