【问题标题】:MFC Processing Files before FoldersMFC 在文件夹之前处理文件
【发布时间】:2018-03-03 00:47:00
【问题描述】:

使用 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
...

我想在进入 \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 是完整层次结构中所有文件的计数:

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。

【问题讨论】:

  • 因为您需要按字母排序,所以无论如何都必须存储目录项(CFileFind 或底层 FindFirstFileFindNextFile API 无法保证您的字母顺序),因此无需担心“矫枉过正”。
  • 不要处理文件和目录,而是这样处理:如果是文件处理它,如果是目录,则将其放入列表中。遍历当前级别的所有文件和目录后,处理列表中的目录。就是这样。

标签: c++ file mfc directory


【解决方案1】:

根据您的描述,您的实际伪代码是这样的:

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 派生一个您自己的类,以确保在迭代期间目录位于文件之后

【讨论】:

  • 我不得不说我对您的回复速度印象深刻。我想我只是太担心保存文件夹列表对于许多深度嵌套的文件夹来说会占用大量内存,但它不会像我想象的那么糟糕。所以你的简单算法和几分钟的编码让我很开心!谢谢! :)
  • CStringArray 不会给出 OP 查找的排序输出。
猜你喜欢
  • 1970-01-01
  • 2020-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多