findの走査順序を記憶したい。 – プログラミング – Home

findの走査順序を記憶したい。
 
通知
すべてクリア

[解決済] findの走査順序を記憶したい。

固定ページ 1 / 2

cc
 cc
(@cc)
ゲスト
結合: 23年前
投稿: 80
Topic starter  

いつも、お世話になっています。

TreeVeiwを作っています。
1.ファイルを指定ディレクトリ内から検索して、結果を記憶します。
2.記憶した関数から引き出して、Treeを作ります。

質問1.以上の順番で、普通のやり方でしょうか。

質問2.検索順序をどう記憶した方がいいでしょうか。
検索走査を追ってみたのですが、
例:
\\Debug\\fiel-1.txt
...
\\Debug\\fiel-10.txt
\\Debug\\複数fiel-1.txt

\\Debug\\複数fiel-5.txt

\\Debug\\新しいフォルダ\\fiel-B.txt

走査結果;
1.fiel-1.txt~fiel-10.txt 順番で検索
2.ファイルの名前は漢字の場合、ファイルを検索しないで、先に、
”新しいフォルダ”を検索しました。
3.”新しいフォルダ”下のfiel-B.txtを検索しました。
4.漢字ファイルを検索しました。

そういうことで、階層な記憶がなかなかうまくできませんでした。

//検索結果の判定
if(FileFind.IsDirectory())
{
 CString Stype =dir;  // フォルダ
 CString IndexsName; // 名前
 IndexsName.Format( %s,%d, Stype, directory_n); //フォルダ+フォルダ番号
 SetCommonPro( m_FielDir_j, Stype, strName, IndexsName);
 directory_n++;    //フォルダの数を数える
 m_FielDir_j++;    //フォルダ+ファイル=総数を数える
 SearchFile(FName, ppth);

else {
 // 検索結果:ファイル
 CString strName = FileFind.GetFileName();
 CString Stype =file;
 CString IndexsName;
 IndexsName.Format( %s,%d, Stype, fiel_n);
 SetCommonPro( m_FielDir_j, Stype, strName, IndexsName);
 fiel_n++;
 m_FielDir_j++;
}

BOOL CRes::SetCommonPro( int ID, CString SType, CString PathName, CString
IndexsName)
{
//この部分が記憶しています。
MU_COMMON* prc;

prc = new MU_COMMON;
pRes->m_MUCOMMON.Add( prc);
prc->id = ID;
prc->type = SType;
prc->PathName = PathName;
  prc->IndexsName = IndexsName;

return TRUE;
}

よろしくお願いします。

環境 XP .net2002 MFC


引用未解決
トピックタグ
maru
 maru
(@maru)
ゲスト
結合: 17年前
投稿: 358
 

「検索順序」って何のことか判断つかないんだけど、ファイル検索でファイルが見つ
かる順序は、ファイルシステムに依存していて辞書順や作成した順序ではない。
したがって表示する際に一定のルールに従って並び替える場合は、自分でソートを
行う必要があるよ。ツリーコントロールにソートしてもらってもいいけど。


返信引用
cc
 cc
(@cc)
ゲスト
結合: 23年前
投稿: 80
Topic starter  

maruさん、ご回答ありがとう。

>「検索順序」って何のことか判断つかないんだけど
同じ階層の場合、ファイルがディレクトリより先処理すること
ではないでしょうか。
(実行みたら、そうではないです。)

走査結果;
\\Debug\\ (親階層)
1.fiel-1.txt~fiel-10.txt 順番で検索 (子供階層)
2.”新しいフォルダ”を検索しました。  (子供兄弟階層)
3.”新しいフォルダ”下のfiel-B.txtを検索しました。(孫階層)
4.漢字ファイルを検索しました。(子供階層を戻る)

問題というのは、4番目の(孫階層)から(子供階層)へ戻りますが、
(子供階層が2回分けて検索された)
判断の方法がわかりません。
ようするに、同じ階層のファイル或いはフォルダをまとめたい、
それができたら、ソートか整理などできます。

よろしくお願いします。


返信引用
ryo
 ryo
(@ryo)
ゲスト
結合: 23年前
投稿: 252
 

フォルダも、『「フォルダ属性」をもってるファイル』なので
「漢字ファイルよりフォルダが先」ではなく
「複より新が先」なだけではないでしょうか


返信引用
maru
 maru
(@maru)
ゲスト
結合: 17年前
投稿: 358
 

何が問題なのかさっぱりわからん。

if(FileFind.IsDirectory())
というコードがあるから、CFileFind クラスを使っていると思うんだけど、このオブジ
ェクトをフォルダ毎に使って、再帰呼び出しをやればエクスプローラのツリーで表示し
ている内容をツリービューに再現することなんて簡単なはずだけど。

> 問題というのは、4番目の(孫階層)から(子供階層)へ戻りますが、
> (子供階層が2回分けて検索された)
> 判断の方法がわかりません。
何を、判断したいの?
あなたのいうところの孫階層と子供階層はIsDirectory()でわかっているでしょ。


返信引用
ryo
 ryo
(@ryo)
ゲスト
結合: 23年前
投稿: 252
 

どっかから完成されたソースをコピーしてきただけかな

ディレクトリが発見されたときに、「再起呼び出し」されてることが分かってないんだと
思う
一回のSearchFile()の呼び出しだけで、
ファイルも、フォルダも、一階層したのファイルも、同じCFileFindから引き出せてると
勘違いしてるんじゃないかな
だから、「孫階層から子供階層に戻るところがわからない」という不思議な疑問がでる

実際は、ディレクトリが見つかったら、再起呼び出しし、
新しいCFileFindをつくって一階層下をファイル検索しなおしてる
だから、ファイルが見つかるたびに、そのときのCFileFindの対象フォルダを保存すれば
いい

と、思ってみたら
> prc->PathName = PathName;
こいつが、検索対象フォルダ(見つけたファイルのおかれているフォルダ)として保存し
てるようだが・・


返信引用
cc
 cc
(@cc)
ゲスト
結合: 23年前
投稿: 80
Topic starter  

ryoさん、maru さん
ご回答ありがとう。

>「複より新が先」なだけではないでしょうか
なるほど。

>ている内容をツリービューに再現することなんて簡単なはずだけど。
そうと思ったのですが、やってみたら、意外な面倒だった。

>何を、判断したいの?
>あなたのいうところの孫階層と子供階層はIsDirectory()でわかっているでしょ。
文字の説明がうまく伝えていなかった。すみませんでした。
走査順序
\\Debug |---(2) fiel-1.txt 等
|---(3) ”新しいフォルダ”|---(4) fiel-B.txt
|---(5) 複数fiel-1.txt 等
そのまま記憶すると、ツリービューに再現することできないでしょう。
(ツリービューは同じ階層の場合、ファイルとフォルダを一機に書き込む)
正解は、
\\Debug |---(2)
    |---(5)
    |---(3) |---(4)
でしょうね、
問題としては、
    |---(5)の階層位置の判断です。((2)と(3)同じ階層)

わかるかなー。

よろしくお願いします。


返信引用
maru
 maru
(@maru)
ゲスト
結合: 17年前
投稿: 358
 

やっぱり何をやりたいのかわからない。
ディレクトリ構造をツリーに展開する処理は以下のとおり。

それで、質問は検索で検出した順序をツリーで表現したいのか?
それとも、フォルダは必ずファイル群より後に表示するようにしたいのか?
のどちらなの?

CTreeCtrl m_tree_ctrl;

// 再帰関数
void Cxxx::Recurse(LPCTSTR path, HTREEITEM hParent)
{
CString strWildcard(path);
strWildcard += _T(\\*.*);
CFileFind finder;

BOOL bWorking = finder.FindFile(strWildcard);
while (bWorking)
{
bWorking = finder.FindNextFile();
if (finder.IsDots())
{
continue;
}
CString str = finder.GetFilePath();
HTREEITEM hItem = m_tree_ctrl.InsertItem(str, hParent, TVI_LAST);
if (finder.IsDirectory())
{
Recurse(str, hItem);
}
}
finder.Close();
}

// 呼び出し元
CString str(_T(Debug));
HTREEITEM hRoot = m_tree_ctrl.InsertItem(str, TVI_ROOT, TVI_LAST);
Recurse(str, hRoot);


返信引用
maru
 maru
(@maru)
ゲスト
結合: 17年前
投稿: 358
 

ファイル群を前にしてフォルダ群を後にする場合

void Cxxx::Recurse(LPCTSTR path, HTREEITEM hParent)
{
CString strWildcard(path);
strWildcard += _T(\\*.*);
CFileFind finder;
HTREEITEM hLastFileItem = TVI_FIRST;

BOOL bWorking = finder.FindFile(strWildcard);
while (bWorking)
{
bWorking = finder.FindNextFile();
if (finder.IsDots())
{
continue;
}
CString str = finder.GetFilePath();
if (finder.IsDirectory())
{
HTREEITEM hItem = m_tree_ctrl.InsertItem(str, hParent, TVI_LAST);
Recurse(str, hItem);
} else
{
hLastFileItem = m_tree_ctrl.InsertItem(str, hParent, hLastFileItem);
}
}
finder.Close();
}

いずれにせよ、ツリーのどの位置に挿入するかは InsertItem の引数 HTREEITEM
hInsertAfter で制御できる。


返信引用
ryo
 ryo
(@ryo)
ゲスト
結合: 23年前
投稿: 252
 

ソースを見た推測ですが

Index Path
Name Name
FileA1 \
FileA2 \
(フォルダ) \
FileB1 \フォルダ\
FileB2 \フォルダ\
FileA3 \

と、必要な情報の両方が保存されている。
しかし、ccさんは、IndexNameだけを、しかも登録された順番にしか見ていないのでしょ

つまり、

FileA1
FileA2
(フォルダ)
FileB1
FileB2
FileA3

というふうに見える。
そのため、FileB2からFileA3になるときに階層が分からなくなると言っている
そこで、ccさんが求めたのは

FileA1
FileA2
(フォルダ)
FileB1
FileB2
(上に戻る) // ここ
FileA3

といった情報だったんだと思います

実際に、SearchFileの動きは

SearchFile(\)
FileA1
FileA2
(フォルダ)→SearchFile( \フォルダ\) //再起呼び出し
FileB1
FileB2
//再起呼び出し終了(SerachFileが終了しただけ)
FileA3

となっているので、ファイル名が一つ一つが保存される際に、
「どのフォルダを検索しているか?」はわかっている

ccさんの求めるものがどうしても欲しいなら、SearchFileの最後に、
「階層をあがる」といった情報をつくってSetCommonPro()を呼び出して登録すればいい。


返信引用
cc
 cc
(@cc)
ゲスト
結合: 23年前
投稿: 80
Topic starter  

ryoさん、maru さん
ご回答ありがとう。

// 再帰関数
>void Cxxx::Recurse(LPCTSTR path, HTREEITEM hParent)
>{...
>}
やってみたら、
FileB1
FileB2
が登録していなっかた。
走査順は以下のようになっています
FileA1 \
FileA2 \
(フォルダ)→SearchFile( \フォルダ\) //再起呼び出し
finder.Close();
FileA3
finder.Close();
原因が不明

ryoさんの推測ほぼ合っています。
実際に以下のようになっています。
Index Path
Name Name
FileA1 \
FileA2 \
(フォルダ) \ FileB1
\ FileB2
FileA3 \

>ccさんの求めるものがどうしても欲しいなら、SearchFileの最後に、
>「階層をあがる」といった情報をつくってSetCommonPro()を呼び出
>して登録すればいい。
「階層をあがる」というのはどう判断するかということです。
目で見て、1ステップ、1ステップがわかっていますが、
プログラム上で判断は今までわかっていません。

よろしくお願いします。


返信引用
cc
 cc
(@cc)
ゲスト
結合: 23年前
投稿: 80
Topic starter  

修正
>原因が不明
CString str = finder.GetFilePath();
の場合正常に
(フォルダ) \ FileB1
\ FileB2
登録できました。

//CString str = finder.GetFileName();
の場合、FileB1検索できません。
CString strWildcard(path);
strWildcard += _T(\\*.*);
のpathが変わっていない(¥Dubug\)

すみませんでした。


返信引用
cc
 cc
(@cc)
ゲスト
結合: 23年前
投稿: 80
Topic starter  

追記
void Cxxx::Recurse(LPCTSTR path, HTREEITEM hParent)
{。。。

は短いPathの場合いいですが、
ドライブ単位にすると表示するまで時間がかかります。
1.finder.FindFile(strWildcard);検索の時間が掛かりますか。
2.HTREEITEM hItem = m_TreeContorol.InsertItem(str2, hParent, TVI_LAST);
  Treeに登録時に時間が掛かりますか。

よろしくお願いします。


返信引用
PATIO
(@patio)
Famed Member
結合: 3年前
投稿: 2660
 

これは掲示板で質問する内容では無いと思います。
なぜなら実測すれば済むだけの話だから。

実際のプログラムの中で時間を図って何処がネックになっているかを
判断すれば良いだけの話です。


返信引用
PATIO
(@patio)
Famed Member
結合: 3年前
投稿: 2660
 

ちなみにですが、

処理対象のデータ量が増えれば、処理時間が増大して
遅くなるのは自然な話です。
単純な組み方でも結果は出せるけれど、
処理対象が増えれば、遅くて使えないという状態になるかもしれません。
その場合は単純に考えている内容をコードに置き換えるだけではなくて
処理順番や処理の方法に工夫をする必要が出てくるでしょう。

遅いのが問題になるレベルであるのならまずはボトルネックを探すのが
先決でしょう。


返信引用
固定ページ 1 / 2

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました