63

I am iterating through all the files in a folder and just want their names in a string. I want to get a string from a std::filesystem::path. How do I do that?

My code:

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

int main()
{
    std::string path = "C:/Users/user1/Desktop";
    for (auto & p : fs::directory_iterator(path))
        std::string fileName = p.path;
}

However I get the following error:

non-standard syntax; use '&' to create a pointer to a member.
tambre
  • 4,625
  • 4
  • 42
  • 55
anonymous noob
  • 807
  • 1
  • 7
  • 10

3 Answers3

92

To convert a std::filesystem::path to a natively-encoded string (whose type is std::filesystem::path::value_type), use the string() method. Note the other *string() methods, which enable you to obtain strings of a specific encoding (e.g. u8string() for an UTF-8 string).

C++17 example:

#include <filesystem>
#include <string>

namespace fs = std::filesystem;

int main()
{
    fs::path path{fs::u8path(u8"愛.txt")};
    std::string path_string{path.u8string()};
}

C++20 example (better language and library UTF-8 support):

#include <filesystem>
#include <string>

namespace fs = std::filesystem;

int main()
{
    fs::path path{u8"愛.txt"};
    std::u8string path_string{path.u8string()};
}
tambre
  • 4,625
  • 4
  • 42
  • 55
  • 2
    if #include and namespace fs = std::filesystem; doesn't work try this one: #include namespace fs = std::experimental::filesystem; – jstar Nov 09 '17 at 08:09
  • 10
    @jstar that's because your standard library is out of date -- time to upgrade :) – Quentin Apr 16 '18 at 12:01
  • 3
    (FYI for newbies like me) `*string()` means, there are `string()`, `wstring()`, `u8string()`, `u16string()`, `u32string()` if you have a look at the source code. – starriet Jul 22 '22 at 14:19
7

In C++ 17 and above, you can use .generic_string() to convert the path to a string: https://en.cppreference.com/w/cpp/filesystem/path/generic_string.

The following is an example that gets the current working directory and converts it into a string.

#include <string>
#include <filesystem>
using std::filesystem::current_path;

int main()
{
    filesystem::path directoryPath = current_path();
    string stringpath = directoryPath.generic_string();
}
voluntier
  • 330
  • 4
  • 11
6

The examples given in the accepted answer, using the UTF-8 operations, are fine and a good guideline. There is just one error in the introductory explanation given in the answer, which Windows/MSVC developers should be aware of:

The string() method does not return the natively-encoded string (which would be std::wstring() on Windows), but rather it always returns a std::string. It also tries to convert the path to the local encoding, which is not always possible, if the path contains a unicode character not representable in the current code page and then the method throws an exception!

If you actually want the behavior that is described in the answer (method returns native string, i.e., std::string on Linux and std::wstring on Windows), you would have to use the native() method or the implicit conversion based on std::filesystem::path::operator string_type(), but as @tambre correctly pointed out in the examples, you should consider using the UTF-8 versions throughout.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
sbricklayer
  • 131
  • 1
  • 5
  • could you show an example that throws on Windows? The cppreference docs don't indicate what happens with the string method there. – Martin Nov 21 '22 at 11:10
  • Nevermind, just managed to reproduce it myself. The exception's `what()` text explicitly says `No mapping for the Unicode character exists in the target multi-byte code page`. I wonder if this is documented anywhere, since at least cppreference doesn't say anything. – Martin Nov 21 '22 at 11:46