Introduction
Imagine that we want to populate a vector with the names of the files in a directory with a read_directory()
function like this:
#include <iostream> #include <string> #include <vector> #include <algorithm> #include <iterator> typedef std::vector<std::string> stringvec; int main() { stringvec v; read_directory(".", v); std::copy(v.begin(), v.end(), std::ostream_iterator<std::string>(std::cout, "\n")); }
There are 4 methods we can use:
- Use
boost::filesystem::directory_iterator
- Use
std::filesystem::directory_iterator
(C++17) - Use
opendir()
/readdir()
/closedir()
(POSIX) - Use
FindFirstFile()
/FindNextFile()
/FindClose()
(Windows)
Method 1: Use boost::filesystem
#include <boost/filesystem.hpp> struct path_leaf_string { std::string operator()(const boost::filesystem::directory_entry& entry) const { return entry.path().leaf().string(); } }; void read_directory(const std::string& name, stringvec& v) { boost::filesystem::path p(name); boost::filesystem::directory_iterator start(p); boost::filesystem::directory_iterator end; std::transform(start, end, std::back_inserter(v), path_leaf_string()); }
Reference: Boost Filesystem Library Version 3
Method 2: Use std::filesystem
(C++17)
#include <filesystem> struct path_leaf_string { std::string operator()(const std::filesystem::directory_entry& entry) const { return entry.path().leaf().string(); } }; void read_directory(const std::string& name, stringvec& v) { std::filesystem::path p(name); std::filesystem::directory_iterator start(p); std::filesystem::directory_iterator end; std::transform(start, end, std::back_inserter(v), path_leaf_string()); }
Method 3: Use opendir()
/readdir()
/closedir()
(POSIX)
#include <sys/types.h> #include <dirent.h> void read_directory(const std::string& name, stringvec& v) { DIR* dirp = opendir(name.c_str()); struct dirent * dp; while ((dp = readdir(dirp)) != NULL) { v.push_back(dp->d_name); } closedir(dirp); }
Reference: readdir – The Open Group
Method 4: Use FindFirstFile()
/FindNextFile()
/FindClose()
(Windows)
#include <windows.h> void read_directory(const std::string& name, stringvec& v) { std::string pattern(name); pattern.append("\\*"); WIN32_FIND_DATA data; HANDLE hFind; if ((hFind = FindFirstFile(pattern.c_str(), &data)) != INVALID_HANDLE_VALUE) { do { v.push_back(data.cFileName); } while (FindNextFile(hFind, &data) != 0); FindClose(hFind); } }
Reference: FindFirstFile function