How to use boost::fs to only load 30 newest files and not the entire directory?
boost, c++, directory, filesystems, macos
Solution
Here's a working example that uses `boost::filter_iterator` with `directory_iterator` to store paths to regular files in a vector. I sorted the vector based on `last_write_time()`. I also ommited error checking for brevity - this example will crash if there's less than 30 files in the directory.
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <boost/filesystem.hpp>
#include <boost/iterator/filter_iterator.hpp>
namespace fs = boost::filesystem;
int main()
{
fs::path p("My image directory");
fs::directory_iterator dir_first(p), dir_last;
std::vector<fs::path> files;
auto pred = [](const fs::directory_entry& p)
{
return fs::is_regular_file(p);
};
std::copy(boost::make_filter_iterator(pred, dir_first, dir_last),
boost::make_filter_iterator(pred, dir_last, dir_last),
std::back_inserter(files)
);
std::sort(files.begin(), files.end(),
[](const fs::path& p1, const fs::path& p2)
{
return fs::last_write_time(p1) < fs::last_write_time(p2);
});
std::copy_n(files.begin(), 30, std::ostream_iterator<fs::path>(std::cout, "\n"));
}
To make your example work, you could structure the for-loop like this:
fs::path pPhoto( photobooth_texture_path );
fs::directory_iterator it( pPhoto );
for ( size_t i = 0; i < 30 && it != fs::directory_iterator(); ++it )
{
if ( fs::is_regular_file( *it ) )
{
// load the image
++i;
}
}
Problem
New to using boost. Using it to load a collection of images. The issue is that the images will continue to grow in number in the folder and I will eventually not want to add all of them to my display program. I am on OS X and using C++. How can I adjust this example code to only load say only 30 images from the top or bottom of the directory? Loading only the newest files would be awesome, but I would settle for just changing this. Unfortunately just saying (it <30) in my loop doesn't work because it needs to be equivalent to fs::directory_iterator. Example code: ``` fs::path pPhoto( photobooth_texture_path ); for ( fs::directory_iterator it( pPhoto ); it != fs::directory_iterator(); ++it ) { if ( fs::is_regular_file( *it ) ) { // -- Perhaps there is a better way to ignore hidden files string photoFileName = it->path().filename().string(); if( !( photoFileName.compare( ".DS_Store" ) == 0 ) ) { photoboothTex.push_back( gl::Texture( loadImage( photobooth_texture_path + photoFileName ), mipFmt) ); cout << "Loaded: " << photoFileName <<endl; } } } ``` EDIT: This is how I ended up doing it. Sort of a hybrid of the two methods, but i needed to sort backwards, even though it won't necessarily be predictably going backwards...taking my chances. Not the cleanest thing in the world, but i had to translate their ideas to a flavor of C++ I understood ``` vector<string> fileList; int count = 0; photoboothTex.clear();//clear this out to make way for new photos fs::path pPhoto( photobooth_texture_path ); for ( fs::directory_iterator it( pPhoto ); it != fs::directory_iterator(); ++it ) { if ( fs::is_regular_file( *it ) ) { // -- Perhaps there is a better way to ignore hidden files string photoFileName = it->path().filename().string(); if( !( photoFileName.compare( ".DS_Store" ) == 0 ) ) { fileList.push_back(photoFileName); } } } for (int i=(fileList.size()-1); i!=0; i--) { photoboothTex.push_back( gl::Texture( loadImage( photobooth_texture_path + fileList[i%fileList.size()] )) ); cout << "Loaded Photobooth: " << fileList[i%fileList.size()] <<endl; if(++count ==40) break; //loads a maximum of 40 images } ```