How do I recursively create a folder in Win32?

前端 未结 14 1250
孤城傲影
孤城傲影 2020-12-01 14:11

I\'m trying to create a function that takes the name of a directory (C:\\foo\\bar, or ..\\foo\\bar\\..\\baz, or \\\\someserver\\foo\\bar

相关标签:
14条回答
  • 2020-12-01 14:23

    Here is my example of code (copied from How can I create directory tree in C++/Linux?). Maybe it's not conform all requirements from first post, but pretty well and it works for both Windows and Linux:

    #include <iostream>
    #include <string>
    #include <sys/stat.h> // stat
    #include <errno.h>    // errno, ENOENT, EEXIST
    #if defined(_WIN32)
    #include <direct.h>   // _mkdir
    #endif
    
    bool isDirExist(const std::string& path)
    {
    #if defined(_WIN32)
        struct _stat info;
        if (_stat(path.c_str(), &info) != 0)
        {
            return false;
        }
        return (info.st_mode & _S_IFDIR) != 0;
    #else 
        struct stat info;
        if (stat(path.c_str(), &info) != 0)
        {
            return false;
        }
        return (info.st_mode & S_IFDIR) != 0;
    #endif
    }
    
    bool makePath(const std::string& path)
    {
    #if defined(_WIN32)
        int ret = _mkdir(path.c_str());
    #else
        mode_t mode = 0755;
        int ret = mkdir(path.c_str(), mode);
    #endif
        if (ret == 0)
            return true;
    
        switch (errno)
        {
        case ENOENT:
            // parent didn't exist, try to create it
            {
                int pos = path.find_last_of('/');
                if (pos == std::string::npos)
    #if defined(_WIN32)
                    pos = path.find_last_of('\\');
                if (pos == std::string::npos)
    #endif
                    return false;
                if (!makePath( path.substr(0, pos) ))
                    return false;
            }
            // now, try to create again
    #if defined(_WIN32)
            return 0 == _mkdir(path.c_str());
    #else 
            return 0 == mkdir(path.c_str(), mode);
    #endif
    
        case EEXIST:
            // done!
            return isDirExist(path);
    
        default:
            return false;
        }
    }
    
    int main(int argc, char* ARGV[])
    {
        for (int i=1; i<argc; i++)
        {
            std::cout << "creating " << ARGV[i] << " ... " << (makePath(ARGV[i]) ? "OK" : "failed") << std::endl;
        }
        return 0;
    }
    

    Usage:

    d:\Work\c++\make_path> makePath 1/2 folderA/folderB/folderC
    creating 1/2 ... OK
    creating folderA/folderB/folderC ... OK
    
    0 讨论(0)
  • 2020-12-01 14:31

    If you don't need to support Windows versions prior to Windows 2000, you can use the SHCreateDirectoryEx function for this. Consider this:

    int createDirectoryRecursively( LPCTSTR path )
    {
        return SHCreateDirectoryEx( NULL, path, NULL );
    }
    
    // ...
    if ( createDirectoryRecursively( T("C:\\Foo\\Bar\\Baz") ) == ERROR_SUCCESS ) {
       // Bingo!
    } 
    

    In case using such shell32.dll API ever becomes an issue, you can always reimplement the createDirectoryRecursively function above with something else (possibly a hand-wired loop).

    0 讨论(0)
  • 2020-12-01 14:31

    From http://www.cplusplus.com/reference/string/string/find_last_of/:

    // string::find_last_of
    #include <iostream>
    #include <string>
    using namespace std;
    
    void SplitFilename (const string& str)
    {
      size_t found;
      cout << "Splitting: " << str << endl;
      found=str.find_last_of("/\\");
      cout << " folder: " << str.substr(0,found) << endl;
      cout << " file: " << str.substr(found+1) << endl;
    }
    
    int main ()
    {
      string str1 ("/usr/bin/man");
      string str2 ("c:\\windows\\winhelp.exe");
    
      SplitFilename (str1);
      SplitFilename (str2);
    
      return 0;
    

    That should give you an idea on how to deal with the path string. Then after that, all you need to do is loop through the paths starting from the drive down to the deepest folder. Check if the folder exists, and if it doesn't, create it.

    0 讨论(0)
  • 2020-12-01 14:32

    With C++17, this can be done quite easily using std::filesystem::create_directories().

    Example:

    #include <filesystem>
    ...
    
    const char* path = "C:\\foo\\bar";
    std::filesystem::create_directories(path);
    
    0 讨论(0)
  • 2020-12-01 14:32

    I'm modifying an old Windows CE app, and this is what I'm planning to use. Should work in Windows CE, too. This is actually recursive, too:

    static void createPath(const CString& p)
    {
       // only create directories that don't exist
       if (::GetFileAttributes(p) == INVALID_FILE_ATTRIBUTES)
       {
          // check if our parent needs to be created, too...
          int i = p.ReverseFind('\\');
          if (i > 0)
          {
             // ...yes, create the parent (recursively)
             createPath(p.Left(i));
          }
    
          // finally, actually create the directory in p
          ::CreateDirectory(p, NULL);
       }
    }
    
    0 讨论(0)
  • 2020-12-01 14:32
    UnicodeString path = "C:\\Test\\Test\\Test\\";
    TStringList *list = new TStringList();
    
    try
    {
        list->Delimiter = '\\';
        list->StrictDelimiter = true;
        list->DelimitedText = path;
        path = list->Strings[0]; \\drive letter
        for(int i = 1; i < list->Count - 1; i++)
        {
            try
            {
                path += "\\" + list->Strings[i];
                CreateDirectory(path.w_str(), NULL);
            }
            catch(...) { }
        }
    }
    catch(...) { }
    delete list;
    
    0 讨论(0)
提交回复
热议问题