How can I extract the file name and extension from a path in C++

Solution 1:

To extract a filename without extension, use boost::filesystem::path::stem instead of ugly std::string::find_last_of(".")

boost::filesystem::path p("c:/dir/dir/file.ext");
std::cout << "filename and extension : " << p.filename() << std::endl; // file.ext
std::cout << "filename only          : " << p.stem() << std::endl;     // file

Solution 2:

For C++17:

#include <filesystem>

std::filesystem::path p("c:/dir/dir/file.ext");
std::cout << "filename and extension: " << p.filename() << std::endl; // "file.ext"
std::cout << "filename only: " << p.stem() << std::endl;              // "file"

Reference about filesystem: http://en.cppreference.com/w/cpp/filesystem

  • std::filesystem::path::filename
  • std::filesystem::path::stem

As suggested by @RoiDanto, for the output formatting, std::out may surround the output with quotations, e.g.:

filename and extension: "file.ext"

You can convert std::filesystem::path to std::string by p.filename().string() if that's what you need, e.g.:

filename and extension: file.ext

Solution 3:

If you want a safe way (i.e. portable between platforms and not putting assumptions on the path), I'd recommend to use boost::filesystem.

It would look somehow like this:

boost::filesystem::path my_path( filename );

Then you can extract various data from this path. Here's the documentation of path object.


BTW: Also remember that in order to use path like

c:\foto\foto2003\shadow.gif

you need to escape the \ in a string literal:

const char* filename = "c:\\foto\\foto2003\\shadow.gif";

Or use / instead:

const char* filename = "c:/foto/foto2003/shadow.gif";

This only applies to specifying literal strings in "" quotes, the problem doesn't exist when you load paths from a file.

Solution 4:

You'll have to read your filenames from the file in std::string. You can use the string extraction operator of std::ostream. Once you have your filename in a std::string, you can use the std::string::find_last_of method to find the last separator.

Something like this:

std::ifstream input("file.log");
while (input)
{
    std::string path;
    input >> path;

    size_t sep = path.find_last_of("\\/");
    if (sep != std::string::npos)
        path = path.substr(sep + 1, path.size() - sep - 1);

    size_t dot = path.find_last_of(".");
    if (dot != std::string::npos)
    {
        std::string name = path.substr(0, dot);
        std::string ext  = path.substr(dot, path.size() - dot);
    }
    else
    {
        std::string name = path;
        std::string ext  = "";
    }
}