0

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?

Community
  • 1
  • 1
Nick X Tsui
  • 2,737
  • 6
  • 39
  • 73
  • Suppose `FindFirstFile` fails. How would you know? It (and many others in the Win32 API) provide extra error info in accordance with their respective documentation. Find which call fails and get any extra error info the documentation says you can get. Then it's a lot easier to help. – chris Jun 03 '16 at 21:31
  • @chris Indeed I have no idea why FindFirsFile failed. I tried to step in, but it seems it is only a library, and there is no source code available. All it returns is a failure I guess. I assume as long as I give it the right path, then it should work, but it seemed not. So I have no idea at this point. – Nick X Tsui Jun 03 '16 at 21:37
  • Use `GetLastError()` to find out **why** it fails. Although if it's not returning `INVALID_HANDLE_VALUE` then it doesn't sound like it actually is failing. – Jonathan Potter Jun 03 '16 at 21:41
  • @JonathanPotter see update. – Nick X Tsui Jun 03 '16 at 21:51

2 Answers2

2

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

Sam
  • 2,473
  • 3
  • 18
  • 29
1

You must use a wildcard character in the end, from the MSDN documentation:

To examine a directory that is not a root directory, use the path to that directory, without a trailing backslash. For example, an argument of "C:\Windows" returns information about the directory "C:\Windows", not about a directory or file in "C:\Windows". To examine the files and directories in "C:\Windows", use an lpFileName of "C:\Windows\*".

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
Tommy Andersen
  • 7,165
  • 1
  • 31
  • 50