Getting a list of filenames

I'm trying to get a list of filenames with a specific extension in the current directory (non-recursive). I want this to be platform independant so I am using the boost::filesystem library. Does anyone know which function I can use to get a filename from a directory_iterator? I saw a few people use leaf() but this appears to be an object of path, not directory_iterator.

This is my code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <vector>
#include <string>
#include <boost/filesystem>
namespace fs = boost::filesystem;

void GetFilenames(std::vector<std::string> &FileNames)
{
    std::string ThisFile;
    fs::path directory(".");
    fs::directory_iterator iter(directory), end;
    
    for(;iter != end; ++iter)
    {
        ThisFile = *iter->leaf();
        if (ThisFile.find(".txt") != std::string::npos)
            FileNames.push_back(iter->leaf());
    }
}
myfile.cpp(399): error C2039: 'leaf' : is not a member of 'boost::filesystem3::directory_entry'
myfile.cpp(402): error C2039: 'leaf' : is not a member of 'boost::filesystem3::directory_entry


As I am new to boost (and non-standard libraries in general) I am having a really tough time finding good documentation on how to do stuff.

Edit: I'm also considering using fs::path::iterator iter but I haven't found a combination that doesn't have 1500 errors.
Last edited on
Almost got it I think. (This is taking a while).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <vector>
#include <string>
#include <boost/filesystem>
namespace fs = boost::filesystem;

void GetFilenames(std::vector<std::string> &FileNames)
{
    fs::path directory(".");
    fs::directory_iterator iter(directory), end;
    
    for(;iter != end; ++iter)
    {
        if (iter->path().extension() == ".txt")
            FileNames.push_back(iter->path().filename());
    }
}
Myfile.cpp(401): error C2440: 'initializing' : cannot convert from 'boost::filesystem3::path' to 'std::basic_string<_Elem,_Traits,_Ax>'
1>          with
1>          [
1>              _Elem=char,
1>              _Traits=std::char_traits<char>,
1>              _Ax=std::allocator<char>
1>          ]
1>          No constructor could take the source type, or constructor overload resolution was ambiguous


Now I can access members of the iterated path. If I cout these values, it works just fine. But storing them in a vector of strings is just not working for me. This makes me thing that the ".txt" comparison may not work as I'd like as well as the type returned by this statement appears to be incompatible with strings.
Okay, I stuck a stringstream in there. It may not be the prettiest thing, but it works. Now i can go to bed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <vector>
#include <sstream>
#include <boost/filesystem>
namespace fs = boost::filesystem;

void GetFilenames(std::vector<std::string> &FileNames)
{
    fs::path directory(".");
    fs::directory_iterator iter(directory), end;
    
    for(;iter != end; ++iter)
    {
        if (iter->path().extension() == ".txt")
        {
            std::stringstream temp;
            temp << iter->path().filename();
            FileNames.push_back(temp.str());
        }
    }
}
Last edited on
You said earlier:
Stewbond wrote:
Now I can access members of the iterated path. If I cout these values, it works just fine. But storing them in a vector of strings is just not working for me. This makes me thing that the ".txt" comparison may not work as I'd like as well as the type returned by this statement appears to be incompatible with strings.


having looked at it - the filesystem part of boost is one of those that have to be compiled - and
defaults to wchar_t on Windows.
But fs::path class has some overloaded file conversion functions to convert the type of string path uses and standard c++ strings.

As follows: - from boost path.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#   ifdef BOOST_WINDOWS_API
    const std::string string() const { return string(codecvt()); } 
    const std::string string(const codecvt_type& cvt) const
    { 
      std::string tmp;
      if (!m_pathname.empty())
        path_traits::convert(&*m_pathname.begin(), &*m_pathname.begin()+m_pathname.size(),
          tmp, cvt);
      return tmp;
    }
    
    //  string_type is std::wstring, so there is no conversion
    const std::wstring&  wstring() const { return m_pathname; }
    const std::wstring&  wstring(const codecvt_type&) const { return m_pathname; }


So you can take away the stringstream and just have
1
2
3
4
5
6
7
8
9
for(;iter != end; ++iter)
    {

       if (iter->path().extension() == ".txt")
        {
            FileNames.push_back( iter->path().filename().string() );
        }
       
    }




Last edited on
Cool it works. Thanks.

This is now very clean:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <vector>
#include <string>
#include <boost/filesystem>
namespace fs = boost::filesystem;

void GetFilenames(std::vector<std::string> &FileNames)
{
    fs::path directory(".");
    fs::directory_iterator iter(directory), end;
    
    for(;iter != end; ++iter)
        if (iter->path().extension() == ".txt")
            FileNames.push_back(iter->path().filename().string());
}
Last edited on
Topic archived. No new replies allowed.