【问题标题】:How to get a list of files (with filter) in folder with Win API如何使用 Win API 获取文件夹中的文件列表(带过滤器)
【发布时间】:2017-10-25 15:22:44
【问题描述】:

我在互联网上搜索了有关获取目录中文件列表的信息,但大多数答案都需要 boost 库。所以我为那些不想添加任何第三方库的人提出这个问题。

那么如何获取目录中的文件列表呢?我们还可以决定我们将要获取的文件的模式(如所有文件、仅 txt 文件、文件名中具有特定文本的文件……)。另外决定是否在子文件夹中搜索。

编辑:我看到这个问题被降级了,可能是因为我没有具体说明这个问题是针对 Win 32 而不是通用 C++(我最近才意识到,当我说 C++ 时,它是没有必要意味着 Win API)。

无论如何,在这个问题中,我的意思是要求 Win API。当然,通用的 C++ 是受欢迎的(因为它也可以与 Windows 一起使用,更好的是它是跨平台的)。

【问题讨论】:

  • 为什么不使用dirent.h
  • @Sniper:例如,因为 Windows 没有 dirent.h。而且由于问题是在不添加第三方库的情况下询问解决方案,因此这不是一般的解决方案。

标签: c++ file winapi directory


【解决方案1】:

C++17有一个std::filesystem::directory_iterator,可以作为

#include <string>
#include <iostream>
#include <filesystem>
namespace fis = std::filesystem;

int main()
{
    std::string dir_path = "path_to_dir";
    for (auto & i : fis::directory_iterator(dir_path))
        std::cout << i << std::endl;
}

另外,std::filesystem::recursive_directory_iterator 也可以迭代子目录。

dirent.h 可以使用,也可用于 windows:

DIR *dir;
struct dirent *s_dir;
if ((dir = opendir ("c:\\programs\\")) != NULL) {
  /* print all the files and directories */
  while ((s_dir = readdir (dir)) != NULL) {
    printf ("%s\n", s_dir->d_name);
  }
  closedir (dir);
} else {
  /* could not open directory */
  perror ("");
  return EXIT_FAILURE;
}

【讨论】:

  • 感谢您的回答 :) 但是要搜索的模式在哪里?
  • C++ 17 很酷,但它只在 2017 年后的编译器中可用。我没有它:(
【解决方案2】:

这里是函数

void GetSubfolderInDirectory(std::vector<TCHAR*> *lstFileOut, const TCHAR* szPath)
{
    HANDLE hFind;
    WIN32_FIND_DATA findData;

    TCHAR szCurrentDir[MAX_PATH];
    _tcscpy_s(szCurrentDir, MAX_PATH, szPath);

    TCHAR szPatternDir[MAX_PATH];
    _tcscpy_s(szPatternDir, MAX_PATH, szCurrentDir);
    _tcscat_s(szPatternDir, MAX_PATH, _T("/*"));
    TCHAR* szFullPath;
    bool bIsDirectory;
    if ((hFind = FindFirstFile(szPatternDir, &findData)) == INVALID_HANDLE_VALUE)
    {
        return;
    }
    do {
        bIsDirectory = (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
        if (bIsDirectory)
        {
            if (findData.cFileName[0] == '.')
            {
                continue;
            }

            szFullPath = (_TCHAR*)malloc(_MAX_PATH * sizeof(_TCHAR));
            _tcscpy_s(szFullPath, MAX_PATH, szCurrentDir);
            _tcscat_s(szFullPath, MAX_PATH, _T("\\"));
            _tcscat_s(szFullPath, MAX_PATH, findData.cFileName);
            lstFileOut->push_back(szFullPath);
        }
    } while (FindNextFile(hFind, &findData));
    FindClose(hFind);
}

void GetFilesInDirectory(std::vector<TCHAR*> *lstFileOut, const TCHAR* szPath, 
    const TCHAR* szPattern, bool bSearchSub)
{
    HANDLE hFind;
    WIN32_FIND_DATA findData;

    TCHAR szCurrentDir[MAX_PATH];
    _tcscpy_s(szCurrentDir, MAX_PATH, szPath);

    TCHAR szPatternDir[MAX_PATH];
    _tcscpy_s(szPatternDir, MAX_PATH, szCurrentDir);
    _tcscat_s(szPatternDir, MAX_PATH, _T("/"));
    _tcscat_s(szPatternDir, szPattern);

    if ((hFind = FindFirstFile(szPatternDir, &findData)) == INVALID_HANDLE_VALUE)
        return; /* No files found */

    TCHAR* szFullPath;
    bool bIsDirectory;
    do {
        szFullPath = (_TCHAR*)malloc(_MAX_PATH * sizeof(_TCHAR));
        _tcscpy_s(szFullPath, MAX_PATH, szCurrentDir);
        _tcscat_s(szFullPath, MAX_PATH, _T("\\"));
        _tcscat_s(szFullPath, MAX_PATH, findData.cFileName);
        bIsDirectory = (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;

        if (findData.cFileName[0] == '.')
        {
            free(szFullPath);
            continue;
        }
        if (bIsDirectory)
        {
            continue;
        }
        else
        {
            lstFileOut->push_back(szFullPath);
        }
    } while (FindNextFile(hFind, &findData));
    FindClose(hFind);

    if (bSearchSub)
    {
        std::vector<TCHAR*> lstDir;
        GetSubfolderInDirectory(&lstDir, szCurrentDir);
        int nFolderCount = lstDir.size();
        for (int i = 0; i < nFolderCount; i++)
        {
            GetFilesInDirectory(lstFileOut, lstDir[i], szPattern, bSearchSub);
        }
    }
}

这里是如何使用

TCHAR szCrtPath[MAX_PATH];
TCHAR szCrtPattern[MAXBYTE];

_tcscpy_s(szCrtPattern, _T("*.*"));
_tcscpy_s(szCrtPath, _MAX_PATH, _T("D:\\MyFolder"));

vector<TCHAR*> lstFile;
GetFilesInDirectory(&lstFile, szCrtPath, szCrtPattern, true);

关于模式的一些解释

*.* // Get all files
*.txt // Get txt file only
*sometext* // Get file with "sometext" in size file name

也许有更好的方法来获取目录中的所有子文件夹(函数 GetSubfolderInDirectory)。

【讨论】:

  • 这不是标准的 C++。它使用 Windows API 函数。
  • @Benjamin Lindley:对不起,在写这个问题时我只是想:第三方-> 非标准;没有第三方 -> 标准
  • 那么,您是否打算为通用 C++ 代码提供此问题的答案?还是您打算在 Windows 上为 C++ 提供答案?如果是前者,那么你的答案是错误的。如果是后者,请更改您的问题。
猜你喜欢
  • 1970-01-01
  • 2013-12-14
  • 2011-01-15
  • 1970-01-01
  • 2023-03-28
  • 1970-01-01
  • 1970-01-01
  • 2014-01-21
  • 2020-02-16
相关资源
最近更新 更多