Search code examples
c++stringfilewinapiwidechar

listing all files in a folder returns empty list


I am referring to this thread to list all files in a folder. Here is the function:

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;
}

Here is how it gets called in the 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;
}

However, I get 0 files in the list. When I was debugging, I found the following line was a false for the if condition.

 if(! (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) 

I don't quite understand why. I obviously have files in the folder. So why am I get a empty list? Thanks a lot.

files in the folder

UPDATE:

I added GetLastError() following while(::FindNextFile(hFind, &fd)); like following:

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

and I got ERROR_NO_MORE_FILES' (18) error. I am confused, because it looks like I have many files in the folder?


Solution

  • Your problem is the filter. basically "D:\\CTData\\64_Slice_Data\\Helical\\fisrt_helical64_data" points to the directory itself. you need to change it to "D:\\CTData\\64_Slice_Data\\Helical\\fisrt_helical64_data\\*.*"

    If I was writing it I would also avoid returning a vector and pass the pointer to the function to be filled.

    #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;
    }
    

    imagine if your function returns 1000s of file names. you don't want to create your list once and then copy it to a new place and then delete the one inside your function. Also change to main function to be the new format.

    Sam