C++ MFC处理文件夹之前的文件
使用MFC,我递归地遍历文件夹结构以获得文件列表。这很好,但在处理文件时,我想先处理一个文件夹中的所有文件,然后再进入子文件夹。例如,如果我有以下层次结构:C++ MFC处理文件夹之前的文件,c++,file,mfc,directory,C++,File,Mfc,Directory,使用MFC,我递归地遍历文件夹结构以获得文件列表。这很好,但在处理文件时,我想先处理一个文件夹中的所有文件,然后再进入子文件夹。例如,如果我有以下层次结构: \A.txt \B.txt \C\C1.txt \C\C2.txt \D.txt \E.txt \F\F1.txt \F\F2.txt \F\F3\F4.txt \F\F3\F5.txt \F\F6.txt \G.txt \H.txt \I.txt ... void GetFiles(CString& strSrcFolder,
\A.txt
\B.txt
\C\C1.txt
\C\C2.txt
\D.txt
\E.txt
\F\F1.txt
\F\F2.txt
\F\F3\F4.txt
\F\F3\F5.txt
\F\F6.txt
\G.txt
\H.txt
\I.txt
...
void GetFiles(CString& strSrcFolder, int& iFound)
{
CString strFileSpec(strSrcFolder);
if (strFileSpec.Right(1) != _T("\\"))
strFileSpec += "\\";
strFileSpec += _T("*.*");
CFileFind Search;
BOOL bFound = Search.FindFile(strFileSpec);
while (bFound) {
bFound = Search.FindNextFile();
if (Search.IsDots())
continue;
if (Search.IsDirectory()) {
if (m_oPrefs.Recurse())
GetFiles(Search.GetFilePath(), iFound);
else
continue;
}
else {
m_vFiles.push_back(Search.GetFilePath());
++iFound;
}
}
Search.Close();
}
我想在进入\C之前处理\(A.txt、B.txt、D.txt、E.txt等)中的所有文件,在进入\F\F3之前处理\F中的所有文件。但是,当我将这些文件收集到std::vector中时,该向量的填充方式与上面的列表完全相同。我怀疑这是因为Windows操作系统的一些内部命令。然后,当我遍历向量并在“路径”部分更改时输出消息时,我得到类似于以下内容的结果:
Processing files in \
Processing files in \C
Processing files in \
Processing files in \F
Processing files in \F\F3
Processing files in \F
Processing files in \
这使得处理过程似乎在文件夹之间来回跳跃,而我更喜欢这样:
Processing files in \
Processing files in \C
Processing files in \F
Processing files in \F\F3
...
并在转移到同级文件夹之前处理完整层次结构中的所有文件。基本上,消息应该根据所使用的文件夹结构按字母顺序显示
我曾想过使用CFileFind::IsDirectory保存一个文件夹列表,直到遍历整个文件夹,然后进入每个已保存的文件夹名称列表并遍历它(并在继续之前保存自己的文件夹列表,等等),但这似乎有些过分了。一定有更好的办法
我当前的代码类似于以下代码,其中iFound是完整层次结构中所有文件的计数:
\A.txt
\B.txt
\C\C1.txt
\C\C2.txt
\D.txt
\E.txt
\F\F1.txt
\F\F2.txt
\F\F3\F4.txt
\F\F3\F5.txt
\F\F6.txt
\G.txt
\H.txt
\I.txt
...
void GetFiles(CString& strSrcFolder, int& iFound)
{
CString strFileSpec(strSrcFolder);
if (strFileSpec.Right(1) != _T("\\"))
strFileSpec += "\\";
strFileSpec += _T("*.*");
CFileFind Search;
BOOL bFound = Search.FindFile(strFileSpec);
while (bFound) {
bFound = Search.FindNextFile();
if (Search.IsDots())
continue;
if (Search.IsDirectory()) {
if (m_oPrefs.Recurse())
GetFiles(Search.GetFilePath(), iFound);
else
continue;
}
else {
m_vFiles.push_back(Search.GetFilePath());
++iFound;
}
}
Search.Close();
}
我希望我已经使我想要完成的事情易于理解,但请不要犹豫,询问是否需要进一步澄清。TIA。根据您的描述,您的实际伪代码如下:
ProcessDirectory(dir)
{
for all items in dir
{
if item is a file
{
ProcessFile(item)
}
else
{ // it's not a file, so it's a directory
ProcessDirectory(dir)
}
}
}
但你需要这个:
ProcessDirectory(dir)
{
list directorylist
for all items in dir
{
if item is a file
{
ProcessFile(item)
}
else
{ // it's not a file, so it's a directory
add item to list
}
}
// now all files of the current directory (dir) have been processed
// now let's process the directories of the current directory (dir)
for all items in list
{
ProcessDirectory(item)
}
}
正如你所看到的,除了列表之外,它几乎是一样的。这绝对不是矫枉过正,我看不到任何更简单的方法
对于列表,您可以使用例如CStringArray MFC类
另一种方法是从CFindFile派生一个您自己的类,以确保在迭代过程中目录位于文件之后。由于需要按字母顺序排序,您必须存储目录项(您不能通过
CFileFind
或基础FindFirstFile
,FindNextFile
API保证字母顺序),因此无需担心“过度杀戮”。与其处理文件和目录,不如这样处理:如果是文件,请处理它,如果是目录,请将其放在列表中。一旦您遍历了当前级别的所有文件和目录,请处理列表中的目录。仅此而已。我不得不说,我对您的答复速度印象深刻。我想我太激动了担心保存文件夹列表对于很多嵌套很深的文件夹来说会占用大量内存,但不会像我想象的那样糟糕。所以你简单的算法和几分钟的编码让我很开心!谢谢!:)CStringArray
不会给出OP所寻找的排序输出。