【问题标题】:listing all files in a folder returns empty list列出文件夹中的所有文件会返回空列表
【发布时间】:2016-10-04 01:43:30
【问题描述】:

我指的是this thread 列出文件夹中的所有文件。这是函数:

vector<string> GetFileList(string path)
{
    vector<string> names;

    WIN32_FIND_DATA fd; 

    LPCSTR pathLPCW = path.c_str();
    HANDLE hFind = ::FindFirstFile(pathLPCW, &fd); 

    if(hFind != INVALID_HANDLE_VALUE) 
    { 
        do 
        { 
            // read all (real) files in current folder
            // , delete '!' read other 2 default folder . and ..
            if(! (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) 
            {

                string fileName(fd.cFileName);
                names.push_back(fileName);
            }

        } while(::FindNextFile(hFind, &fd)); 

        ::FindClose(hFind); 
    }

    return names;
}

这是它在 main 中的调用方式:

int _tmain(int argc, _TCHAR* argv[])
{
    string path = "D:\\CTData\\64_Slice_Data\\Helical\\fisrt_helical64_data";


    vector<string> fileList = GetFileList(path);
    return 0;
}

但是,我在列表中得到 0 个文件。在调试时,我发现以下行对于 if 条件是错误的。

 if(! (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) 

我不太明白为什么。我显然在文件夹中有文件。那么为什么我得到一个空列表?非常感谢。

更新:

我在 while(::FindNextFile(hFind, &fd)); 之后添加了 GetLastError()如下:

while(::FindNextFile(hFind, &fd)); 
        lastError  = GetLastError();

我得到了ERROR_NO_MORE_FILES' (18) 错误。我很困惑,因为看起来我的文件夹中有很多文件?

【问题讨论】:

  • 假设 FindFirstFile 失败。你怎么知道的?它(以及 Win32 API 中的许多其他 API)根据各自的文档提供额外的错误信息。查找哪个调用失败并获取文档说您可以获得的任何额外错误信息。那么提供帮助就容易多了。
  • @chris 确实我不知道 FindFirsFile 失败的原因。我试图介入,但它似乎只是一个库,并且没有可用的源代码。我猜它返回的只是失败。我认为只要我给它正确的路径,那么它应该可以工作,但似乎没有。所以我现在不知道。
  • 使用GetLastError() 找出为什么它失败了。虽然如果它没有返回INVALID_HANDLE_VALUE,那么它听起来并不像它实际上正在失败。
  • @JonathanPotter 查看更新。

标签: c++ string file winapi widechar


【解决方案1】:

您的问题是过滤器。基本上"D:\\CTData\\64_Slice_Data\\Helical\\fisrt_helical64_data" 指向目录本身。你需要把它改成"D:\\CTData\\64_Slice_Data\\Helical\\fisrt_helical64_data\\*.*"

如果我正在编写它,我也会避免返回向量并将指针传递给要填充的函数。

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

using namespace std;

typedef vector<wstring> TFileList;

void GetFileList(wstring path, TFileList* pFileList)
{
    WIN32_FIND_DATA fd;

    HANDLE hFind = ::FindFirstFile(path.c_str(), &fd);

    if (hFind != INVALID_HANDLE_VALUE)
    {
        do
        {
            // read all (real) files in current folder
            // , delete '!' read other 2 default folder . and ..
            if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
            {
                wstring fileName(fd.cFileName);
                pFileList->push_back(fileName);
            }

        } while (::FindNextFile(hFind, &fd));

        ::FindClose(hFind);
    }
}

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
{
    wstring path = {L"D:\\CTData\\64_Slice_Data\\Helical\\fisrt_helical64_data\\*.*"};
    TFileList names;

    GetFileList(path, &names);
    return 0;
}

想象一下,如果您的函数返回 1000 个文件名。您不想创建一次列表,然后将其复制到新位置,然后删除函数内的列表。 也将main 函数更改为新格式。

山姆

【讨论】:

  • 你是绝对正确的。有效。非常感谢!
  • 顺便说一句。建议你把string全部改成wstring
  • 好的。我能问为什么吗?
  • 也可以从 DOS 继续使用 *
  • Windows 使用 wchar_t 作为文件名。这样,如果您有一个带有宽字符的文件名,您的函数将不会返回垃圾。此外,在现代操作系统中,为 Unicode 做好准备是一个好习惯。
【解决方案2】:

最后必须使用通配符,来自MSDN documentation:

要检查不是根目录的目录,请使用该目录的路径,后面不带反斜杠。例如,“C:\Windows”的参数返回关于目录“C:\Windows”的信息,而不是关于“C:\Windows”中的目录或文件的信息。要检查“C:\Windows”中的文件和目录,请使用“C:\Windows\*”的 lpFileName。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-07-02
    • 1970-01-01
    • 2012-12-27
    • 2018-08-06
    • 1970-01-01
    • 1970-01-01
    • 2023-01-13
    • 2013-05-08
    相关资源
    最近更新 更多