【问题标题】:How do I list subdirectories in Windows using C++?如何使用 C++ 列出 Windows 中的子目录?
【发布时间】:2011-09-02 06:46:48
【问题描述】:

如何使用 C++ 在 Windows 中列出子目录?使用可以跨平台运行的代码会更好。

【问题讨论】:

  • 首先,你搜索,然后你尝试一些东西,然后发布你卡住的代码。
  • @Etienne :为什么要链接到将近两年前的版本的文档?从那时起,Boost.Filesystem 的 API 发生了显着变化(v3 与 v2),因此值得链接到 current docs
  • @avee :您说您想要一个适用于 Windows 的解决方案,最好是跨平台的,并且遵守 POSIX 标准?下定决心...... ;-](真的,选择一个。)

标签: c++ windows subdirectory


【解决方案1】:

这是我的问题解决方案,但它是仅适用于 Windows 的解决方案。我想使用跨平台解决方案,但不使用 boost。

#include <Windows.h>
#include <vector>
#include <string>

/// Gets a list of subdirectories under a specified path
/// @param[out] output Empty vector to be filled with result
/// @param[in]  path   Input path, may be a relative path from working dir
void getSubdirs(std::vector<std::string>& output, const std::string& path)
{
    WIN32_FIND_DATA findfiledata;
    HANDLE hFind = INVALID_HANDLE_VALUE;

    char fullpath[MAX_PATH];
    GetFullPathName(path.c_str(), MAX_PATH, fullpath, 0);
    std::string fp(fullpath);

    hFind = FindFirstFile((LPCSTR)(fp + "\\*").c_str(), &findfiledata);
    if (hFind != INVALID_HANDLE_VALUE)
    {
        do 
        {
            if ((findfiledata.dwFileAttributes | FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY
                && (findfiledata.cFileName[0] != '.'))
            {
                output.push_back(findfiledata.cFileName);
            }
        } 
        while (FindNextFile(hFind, &findfiledata) != 0);
    }
}

/// Gets a list of subdirectory and their subdirs under a specified path
/// @param[out] output Empty vector to be filled with result
/// @param[in]  path   Input path, may be a relative path from working dir
/// @param[in]  prependStr String to be pre-appended before each result
///                        for top level path, this should be an empty string
void getSubdirsRecursive(std::vector<std::string>& output, 
                         const std::string& path,
                         const std::string& prependStr)
{
    std::vector<std::string> firstLvl;
    getSubdirs(firstLvl, path);
    for (std::vector<std::string>::iterator i = firstLvl.begin(); 
         i != firstLvl.end(); ++i)
    {
        output.push_back(prependStr + *i);
        getSubdirsRecursive(output, 
            path + std::string("\\") + *i + std::string("\\"),
            prependStr + *i + std::string("\\"));
    }
}

【讨论】:

  • 感谢您的回答.. 真的很有帮助。
  • 此算法不检测带有自定义图标的文件夹。
  • 一个错误的算法,抱歉 :)
  • 该算法似乎正确地进行了递归,但是 getSubdirs 不能可靠地检测文件是否为目录类型。以下 if 条件不正确: if (findfiledata.dwFileAttributes | FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY) 调整有问题的 if 条件以使用以下条件,而不是使算法可靠地为我工作: if (findfiledata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 请参阅@ 987654321@了解更多详情
【解决方案2】:

【讨论】:

  • 隐藏的技巧是 GetFileAttributes 将指示文件是目录还是常规文件。此外,此解决方案肯定适用于 XP。 (也可能是 Windows 95)。
  • @selbie 您还可以检查上述函数的WIN32_FIND_DATA.dwFileAttributes 部分结果中的FILE_ATTRIBUTE_DIRECTORY 值,以检查结果是否为目录。您还应该检查...,因为它们也会作为结果返回。
  • 选择这个作为答案,因为这是我在解决方案中实际使用的。
【解决方案3】:

这是一个相对较好的解决方案,应该可以跨平台工作。您必须更改您希望它做某事的代码部分,否则它应该工作得很好。

#include <cstring>
#include <io.h>
#include <iostream>
#include <stdio.h>

using namespace std;

void list(char* dir)
{
    char originalDirectory[_MAX_PATH];

    // Get the current directory so we can return to it
    _getcwd(originalDirectory, _MAX_PATH);

    _chdir(dir);  // Change to the working directory
    _finddata_t fileinfo;

    // This will grab the first file in the directory
    // "*" can be changed if you only want to look for specific files
    intptr_t handle = _findfirst("*", &fileinfo);

    if(handle == -1)  // No files or directories found
    {
        perror("Error searching for file");
        exit(1);
    }

    do
    {
        if(strcmp(fileinfo.name, ".") == 0 || strcmp(fileinfo.name, "..") == 0)
            continue;
        if(fileinfo.attrib & _A_SUBDIR) // Use bitmask to see if this is a directory
            cout << "This is a directory." << endl;
        else
            cout << "This is a file." << endl;
    } while(_findnext(handle, &fileinfo) == 0);

    _findclose(handle); // Close the stream

    _chdir(originalDirectory);
}

int main()
{
    list("C:\\");
    return 0;
}

这是非常简洁的代码,将列出目录中的所有子目录和文件。如果你想让它列出每个子目录中的所有内容,你可以通过在打印出“这是一个目录”的行中传入子目录来递归调用该函数。类似 list(fileinfo.name);应该做的伎俩。

【讨论】:

    【解决方案4】:

    看看Boost.Filesystem。它是跨平台且免费的。

    【讨论】:

      【解决方案5】:

      您可以使用 dirent 围兜。更多详情here

      【讨论】:

      • 您介意在您的答案中包含链接文章的相关部分吗?链接可能会改变,使您的答案对未来的读者来说已经过时和无用。另请参阅How to Answer
      猜你喜欢
      • 1970-01-01
      • 2012-01-31
      • 2011-01-19
      • 2017-06-22
      • 1970-01-01
      • 2017-05-15
      • 2010-12-15
      • 2011-11-09
      • 1970-01-01
      相关资源
      最近更新 更多