【问题标题】:How can I obtain all of the file names in a directory?如何获取目录中的所有文件名?
【发布时间】:2016-03-07 06:07:02
【问题描述】:

我正在用 C++ 编写程序。我正在尝试获取程序可执行文件所在文件夹中的所有文件并将它们存储在向量中。我被告知下面的代码应该可以工作,但是 FindFirstFile 操作只能找到一个文件(它应该搜索的文件夹的名称)。如何更改代码以便正确查看文件夹?

std::vector<char*> fileArray;

//Get location of program executable
HMODULE hModule = GetModuleHandleW(NULL);
WCHAR path[MAX_PATH];
GetModuleFileNameW(hModule, path, MAX_PATH);

//Remove the executable file name from 'path' so that it refers to the folder instead
PathCchRemoveFileSpec(path, sizeof(path));

//This code should find the first file in the executable folder, but it fails
//Instead, it obtains the name of the folder that it is searching
WIN32_FIND_DATA ffd;
HANDLE hFind = INVALID_HANDLE_VALUE;
hFind = FindFirstFile(path, &ffd);

do
{
    //The name of the folder is pushed onto the array because of the previous code's mistake
    //e.g. If the folder is "C:\\MyFolder", it stores "MyFolder"
    fileArray.push_back(ffd.cFileName); //Disclaimer: This line of code won't add the file name properly (I'll get to fixing it later), but that's not relevant to the question
} while (FindNextFile(hFind, &ffd) != 0); //This line fails to find anymore files

【问题讨论】:

  • 试过把 \* 放在路径的末尾吗?

标签: c++ windows file directory


【解决方案1】:

有人告诉我下面的代码应该可以工作

你被告知错了,因为你提供的代码被严重破坏了。

FindFirstFile 操作只找到一个文件(它应该搜索的文件夹的名称)。

您仅将文件夹路径本身传递给FindFirstFile(),因此只会报告一个条目,描述文件夹本身。您需要做的是在路径末尾附加一个**.* 通配符,然后FindFirstFile()/FindNextFile() 将枚举文件夹内的文件和子文件夹。

除此之外,代码还有其他几个问题。

即使枚举工作正常,您也不会区分文件和子文件夹。

您将错误的值传递给PathCchRemoveFileSpec() 的第二个参数。您正在传递一个 byte 计数,但它需要一个 character 计数。

在进入循环之前,您没有检查 FindFirstFile() 是否失败,并且在循环完成后您没有调用 FindClose()

最后,您的代码甚至无法按原样编译。您的vector 存储char* 值,但是为了将WCHAR[] 传递给FindFirstFile(),必须定义UNICODE,这意味着FindFirstFile() 将映射到FindFirstFileW()WIN32_FIND_DATA 将映射到WIN32_FIND_DATAW,因此cFileName 字段将是WCHAR[]。编译器不允许将WCHAR[](或WCHAR*) 分配给char*

试试类似的方法:

std::vector<std::wstring> fileArray;

//Get location of program executable
WCHAR path[MAX_PATH+1] = {0};
GetModuleFileNameW(NULL, path, MAX_PATH);

//Remove the executable file name from 'path' so that it refers to the folder instead
PathCchRemoveFileSpec(path, MAX_PATH);

// append a wildcard to the path
PathCchAppend(path, MAX_PATH, L"*.*");

WIN32_FIND_DATAW ffd;
HANDLE hFind = FindFirstFileW(path, &ffd);
if (hFile != INVALID_HANDLE_VALUE)
{
    do
    {
        if ((ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
            fileArray.push_back(ffd.cFileName);
    }
    while (FindNextFileW(hFind, &ffd));
    FindClose(hFind);
}

【讨论】:

  • 这段代码确实准确地获取了所有文件,但是我如何才能以 char* 形式获取它们而不是 wstring?
  • 如果您希望您的程序正常运行,请不要这样做。 (如果其中一个文件名包含不在当前代码页中的字符怎么办?)
  • @Ben:Harry 是对的,你真的不应该 Ansi-fy 你的代码。 Windows 是 Unicode 操作系统,NTFS 使用 Unicode 文件名。您应该对所有内容都使用 Unicode。话虽如此,如果您确实需要char 格式的文件名而不是WCHAR,请使用WideCharToMultiByte() 将文件名从WCHAR 转换为char,或者改用FindFirstFileA()/FindNextFileA() FindFirstFileW()/FindNextFileW()...
  • @Ben: ... 在这种情况下,您的path 也需要采用char 格式。您可以为此使用GetModuleFileNameA()PathCchRemoveFileSpec()PathCchAppend()不支持char数据,只支持WCHAR数据,但PathRemoveFileSpecA()PathAppendA()支持char
猜你喜欢
  • 1970-01-01
  • 2012-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-20
  • 1970-01-01
  • 1970-01-01
  • 2011-10-27
相关资源
最近更新 更多