19

I was wondering if there's an easy way in C++ to read a number of file names from a folder containing many files. They are all bitmaps if anyone is wondering.

I don't know much about Windows programming so I was hoping it can be done using simple C++ methods.

hippietrail
  • 15,848
  • 18
  • 99
  • 158
Tony R
  • 11,224
  • 23
  • 76
  • 101
  • 4
    See also [How can I get the list of files in a directory using C or C++](http://stackoverflow.com/questions/612097/how-can-i-get-the-list-of-files-in-a-directory-using-c-or-c). – Jonathan Leffler Dec 25 '14 at 01:53

8 Answers8

20

Boost provides a basic_directory_iterator which provides a C++ standard conforming input iterator which accesses the contents of a directory. If you can use Boost, then this is at least cross-platform code.

chrish
  • 2,352
  • 1
  • 17
  • 32
18

C++17 includes a standard way of achieve that

http://en.cppreference.com/w/cpp/filesystem/directory_iterator

#include <fstream>
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;

int main()
{
    fs::create_directories("sandbox/a/b");
    std::ofstream("sandbox/file1.txt");
    std::ofstream("sandbox/file2.txt");
    for(auto& p: fs::directory_iterator("sandbox"))
        std::cout << p << '\n';
    fs::remove_all("sandbox");
}

Possible output:

sandbox/a
sandbox/file1.txt
sandbox/file2.txt
robermorales
  • 3,293
  • 2
  • 27
  • 36
13

Since you specify Windows,

I think you're looking for FindFirstFile() and FindNextFile().

hippietrail
  • 15,848
  • 18
  • 99
  • 158
John T
  • 23,735
  • 11
  • 56
  • 82
9

Just had a quick look in my snippets directory. Found this. This uses Microsoft's Win32 API directly:

vector<CStdString> filenames;
CStdString directoryPath("C:\\foo\\bar\\baz\\*");

WIN32_FIND_DATA FindFileData; 
HANDLE hFind = FindFirstFile(directoryPath, &FindFileData);

if (hFind  != INVALID_HANDLE_VALUE)
{
    do
    {
        if (FindFileData.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY)
              filenames.push_back(FindFileData.cFileName);
    } while (FindNextFile(hFind, &FindFileData));

    FindClose(hFind);
}

This gives you a vector with all filenames in a directory. It only works on Windows of course.


João Augusto noted in an answer:

Don't forget to check after FindClose(hFind) for:

DWORD dwError = GetLastError();
if (dwError != ERROR_NO_MORE_FILES) 
{
  // Error happened        
}

It's especially important if scanning on a network.

hippietrail
  • 15,848
  • 18
  • 99
  • 158
drby
  • 2,619
  • 25
  • 26
7

You could also use the POSIX opendir() and readdir() functions. See this manual page which also has some great example code.

slacy
  • 11,397
  • 8
  • 56
  • 61
4

Since you are programming for Windows I recommend you to use the native Win32 FindFirstFile() and FindNextFile() functions. These give you full control over how you search for files. These are simple C APIs and are not hard to use.

Another advantage is that Win32 errors are not hidden or made harder to get at due to the C/C++ library layer.

hippietrail
  • 15,848
  • 18
  • 99
  • 158
Foredecker
  • 7,395
  • 4
  • 29
  • 30
0

Another alternative is -

  1. system("dir | findstr \".bmp\" > temp.txt ");
  2. Now read temp.txt line by line to get all filenames.
herohuyongtao
  • 49,413
  • 29
  • 133
  • 174
Vaibhav Gorde
  • 189
  • 1
  • 1
  • 7
-1

Why not use glob()?

glob_t glob_result;
glob("/foo/bar/*",GLOB_TILDE,NULL,&glob_result);
for(unsigned int i=0;i<glob_result.gl_pathc;++i){
  cout << glob_result.gl_pathv[i] << endl;
}
Meekohi
  • 10,390
  • 6
  • 49
  • 58