Get a file name from a path

前端 未结 21 1425
面向向阳花
面向向阳花 2020-11-30 23:55

What is the simplest way to get the file name that from a path?

string filename = \"C:\\\\MyDirectory\\\\MyFile.bat\"

In this example, I s

相关标签:
21条回答
  • 2020-12-01 00:17

    A possible solution:

    string filename = "C:\\MyDirectory\\MyFile.bat";
    
    // Remove directory if present.
    // Do this before extension removal incase directory has a period character.
    const size_t last_slash_idx = filename.find_last_of("\\/");
    if (std::string::npos != last_slash_idx)
    {
        filename.erase(0, last_slash_idx + 1);
    }
    
    // Remove extension if present.
    const size_t period_idx = filename.rfind('.');
    if (std::string::npos != period_idx)
    {
        filename.erase(period_idx);
    }
    
    0 讨论(0)
  • 2020-12-01 00:17

    C++11 variant (inspired by James Kanze's version) with uniform initialization and anonymous inline lambda.

    std::string basename(const std::string& pathname)
    {
        return {std::find_if(pathname.rbegin(), pathname.rend(),
                             [](char c) { return c == '/'; }).base(),
                pathname.end()};
    }
    

    It does not remove the file extension though.

    0 讨论(0)
  • 2020-12-01 00:18
    m_szFilePath.MakeLower();
    CFileFind finder;
    DWORD buffSize = MAX_PATH;
    char longPath[MAX_PATH];
    DWORD result = GetLongPathName(m_szFilePath, longPath, MAX_PATH );
    
    if( result == 0)
    {
        m_bExists = FALSE;
        return;
    }
    m_szFilePath = CString(longPath);
    m_szFilePath.Replace("/","\\");
    m_szFilePath.Trim();
    //check if it does not ends in \ => remove it
    int length = m_szFilePath.GetLength();
    if( length > 0 && m_szFilePath[length - 1] == '\\' )
    {
        m_szFilePath.Truncate( length - 1 );
    }
    BOOL bWorking = finder.FindFile(this->m_szFilePath);
    if(bWorking){
        bWorking = finder.FindNextFile();
        finder.GetCreationTime(this->m_CreationTime);
        m_szFilePath = finder.GetFilePath();
        m_szFileName = finder.GetFileName();
    
        this->m_szFileExtension = this->GetExtension( m_szFileName );
    
        m_szFileTitle = finder.GetFileTitle();
        m_szFileURL = finder.GetFileURL();
        finder.GetLastAccessTime(this->m_LastAccesTime);
        finder.GetLastWriteTime(this->m_LastWriteTime);
        m_ulFileSize = static_cast<unsigned long>(finder.GetLength());
        m_szRootDirectory = finder.GetRoot();
        m_bIsArchive = finder.IsArchived();
        m_bIsCompressed = finder.IsCompressed();
        m_bIsDirectory = finder.IsDirectory();
        m_bIsHidden = finder.IsHidden();
        m_bIsNormal = finder.IsNormal();
        m_bIsReadOnly = finder.IsReadOnly();
        m_bIsSystem = finder.IsSystem();
        m_bIsTemporary = finder.IsTemporary();
        m_bExists = TRUE;
        finder.Close();
    }else{
        m_bExists = FALSE;
    }
    

    The variable m_szFileName contains the fileName.

    0 讨论(0)
  • 2020-12-01 00:19

    Function:

    #include <string>
    
    std::string
    basename(const std::string &filename)
    {
        if (filename.empty()) {
            return {};
        }
    
        auto len = filename.length();
        auto index = filename.find_last_of("/\\");
    
        if (index == std::string::npos) {
            return filename;
        }
    
        if (index + 1 >= len) {
    
            len--;
            index = filename.substr(0, len).find_last_of("/\\");
    
            if (len == 0) {
                return filename;
            }
    
            if (index == 0) {
                return filename.substr(1, len - 1);
            }
    
            if (index == std::string::npos) {
                return filename.substr(0, len);
            }
    
            return filename.substr(index + 1, len - index - 1);
        }
    
        return filename.substr(index + 1, len - index);
    }
    

    Tests:

    #define CATCH_CONFIG_MAIN
    #include <catch/catch.hpp>
    
    TEST_CASE("basename")
    {
        CHECK(basename("") == "");
        CHECK(basename("no_path") == "no_path");
        CHECK(basename("with.ext") == "with.ext");
        CHECK(basename("/no_filename/") == "no_filename");
        CHECK(basename("no_filename/") == "no_filename");
        CHECK(basename("/no/filename/") == "filename");
        CHECK(basename("/absolute/file.ext") == "file.ext");
        CHECK(basename("../relative/file.ext") == "file.ext");
        CHECK(basename("/") == "/");
        CHECK(basename("c:\\windows\\path.ext") == "path.ext");
        CHECK(basename("c:\\windows\\no_filename\\") == "no_filename");
    }
    
    0 讨论(0)
  • 2020-12-01 00:20
    std::string getfilename(std::string path)
    {
        path = path.substr(path.find_last_of("/\\") + 1);
        size_t dot_i = path.find_last_of('.');
        return path.substr(0, dot_i);
    }
    
    0 讨论(0)
  • 2020-12-01 00:22

    The simplest solution is to use something like boost::filesystem. If for some reason this isn't an option...

    Doing this correctly will require some system dependent code: under Windows, either '\\' or '/' can be a path separator; under Unix, only '/' works, and under other systems, who knows. The obvious solution would be something like:

    std::string
    basename( std::string const& pathname )
    {
        return std::string( 
            std::find_if( pathname.rbegin(), pathname.rend(),
                          MatchPathSeparator() ).base(),
            pathname.end() );
    }
    

    , with MatchPathSeparator being defined in a system dependent header as either:

    struct MatchPathSeparator
    {
        bool operator()( char ch ) const
        {
            return ch == '/';
        }
    };
    

    for Unix, or:

    struct MatchPathSeparator
    {
        bool operator()( char ch ) const
        {
            return ch == '\\' || ch == '/';
        }
    };
    

    for Windows (or something still different for some other unknown system).

    EDIT: I missed the fact that he also wanted to suppress the extention. For that, more of the same:

    std::string
    removeExtension( std::string const& filename )
    {
        std::string::const_reverse_iterator
                            pivot
                = std::find( filename.rbegin(), filename.rend(), '.' );
        return pivot == filename.rend()
            ? filename
            : std::string( filename.begin(), pivot.base() - 1 );
    }
    

    The code is a little bit more complex, because in this case, the base of the reverse iterator is on the wrong side of where we want to cut. (Remember that the base of a reverse iterator is one behind the character the iterator points to.) And even this is a little dubious: I don't like the fact that it can return an empty string, for example. (If the only '.' is the first character of the filename, I'd argue that you should return the full filename. This would require a little bit of extra code to catch the special case.) }

    0 讨论(0)
提交回复
热议问题