Listing files in a directory in C++

First of all I am not sure how you go about doing this in unix or linux! There is no standard, platform specific way to get all the files in a directory, however the following method works on windows making use of calls to winAPI so dont forget to include this!

#include <windows.h>

The following code then loops through a folder (in this case the starting folder of the executable) and puts the filenames into a string array.  The functions FindFirstFile and FindNextFile both work by populating a structure of the type WIN32_FIND_DATA which holds all the properties of the file in question.

UINT counter(0);
bool working(true);
string buffer;
string fileName[1000];

WIN32_FIND_DATA myimage;
HANDLE myHandle=FindFirstFile("*.jpg",&myimage);

if(myHandle!=INVALID_HANDLE_VALUE)
{
       buffer=myimage.cFileName;
       fileName[counter]=buffer;

       while(working)
       {
              FindNextFile(myHandle,&myimage);
              if(myimage.cFileName!=buffer)
              {
                     buffer=myimage.cFileName;
                     ++counter;
                     fileName[counter]=buffer;
              }
              else
              {
                      //end of files reached
                      working=false;
              }

       }
}

When the last file in the folder has been read, the FindNextFile method will keep returning the same filename over and over again in the while loop. To catch this i use a sort of swap buffer to check if the same filename is found twice, and if so exiting the loop. I am sure there is a better way to catch the last file and will look into this soon. If anyone knows a more efficient way to do this please let me know.

NOTE:- “*.jpg” could be replaced with “C:/myfolder” or “*.doc” or a combination of the two depending on how you wish to filter the files that are found.  Using “” would list all the files in the running directory of the executable.

6 comments to Listing files in a directory in C++

  1. FindNextFile() fails when the last file is reached. The following stores the names of all the files and folders in the current directory in a STL vector of strings.

    void listCurDir(std::vector& fnVec)
    {
    WIN32_FIND_DATA fd;
    HANDLE h = FindFirstFile(“*.*”, &fd);
    fnVec.clear();
    fnVec.push_back(fd.cFileName);
    while (FindNextFile(h, &fd))
    fnVec.push_back(fd.cFileName);
    }

  2. TooTiredToTango says:

    Seems to me you are doing this the hard way…

    Based on your code you could have used FindFirstFile to look directly for the filename…

    FindFirstFile(&buffer,&myimage)

    It would have found the first occurance of your file in the directory with no need to search every file looking for it.

  3. Alireza from Tehran Polytechnic says:

    Please accept my gratitude!
    Your sweet code made my life easier!

  4. I’m using boost::file_system for a cross platform solution to this. I only mention this as you mention Linux in there. (And maybe because I dislike using but that’s another story ;) )

    namespace fs = boost::file_system;

    void ClientPhysicsHandler::recurseResources(const std::string &path)
    {
    fs::path dir(path);
    fs::directory_iterator end_dir;
    for(fs::directory_iterator it(dir); it != end_dir; it++)
    {
    if(fs::is_directory(it->status()))
    recurseResources(it->path().directory_string());
    if(Util::endsWith(it->leaf(), “.hkx”))
    {
    loadResource(it->path().file_string());
    }
    }
    }

    This code recurses and performs an action on any file that matches a pattern. It can obviously be modified to do something else, such as search for files and return matches or the like.

  5. kerchunk says:

    // I expanded on your efforts a bit, fixing the loop termination

    #include “stdafx.h”
    #include
    #include
    #include
    #include

    using namespace std;

    int main(int argc, char* argv[] ) {

    int nRetCode = 0;

    //WIN32 API method
    string buffer;
    vector fileNames;
    WIN32_FIND_DATA findFileData;
    HANDLE myHandle=FindFirstFile( “*.*”, &findFileData);

    if( myHandle != INVALID_HANDLE_VALUE) { //found at least one file
    buffer = findFileData.cFileName;
    fileNames.push_back( buffer);
    while( FindNextFile( myHandle, &findFileData) != 0) {
    buffer = findFileData.cFileName;
    fileNames.push_back( buffer);
    }
    }
    FindClose( myHandle);

    for( vector::iterator mj = fileNames.begin() ; mj != fileNames.end() ; mj++ ) {
    cout << *mj << endl;

    }

    return nRetCode;
    }

  6. Steven Wang says:

    bool working = TRUE; is not necessary.

    FileNextFile might return 0; if GetLastError() returns ERROR_NO_MORE_FILES, then that’s it.

    So.
    while(FindNextFile) {
    }

    will work