How do I recursively create a folder in Win32?

前端 未结 14 1249
孤城傲影
孤城傲影 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:11

    ctacke You forgot the last segment. e.g. '\aa\bb\"cc"' Following is the modification for ctacke:

    //---------------------------------------------------------------------
    int isfexist(char *fn)
    {
        struct stat stbuf;
        extern int errno;
    
        if (stat(fn, &stbuf)) {
            if (errno == ENOENT) return(0);
            else {
                printf("isfexist: stat");
                return(0);
            }
        } else {
            if (stbuf.st_mode & S_IFDIR) return(2);
            else return(1);
        }
    }
    //---------------------------------------------------------------------
    int MakeDirTree(char *path)
    {
        char *end1, *end2;
    
        if (path[0] == '\\') end1 = path + 1;       // Case '\aa\bb'
        else if (path[1] == ':' && path[2] == '\\') end1 = path + 3;    // Case 'C:\\aa\\bb'
        else end1 = path;
    
        for(;;) {
            end2 = strchr(end1, '\\');
            if (end2 == NULL) {
                // Case '\aa\bb\'
                if (*end1 == 0) break;
                // Last segment '\aa\bb\"cc"' not yet proceed
            } else *end2 = 0;
            if (isfexist(path) <= 0) mkdir(path);
            if (end2 == NULL) break;    // Last segment finished
            else {
                *end2 = '\\';
                end1 = end2 + 1;
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-01 14:15

    Here is a function I wrote which iteratively creates a folder tree. Here is the main function:

    #include <io.h>
    #include <string>
    #include <direct.h>
    #include <list>
    
    // Returns false on success, true on error
    bool createFolder(std::string folderName) {
        list<std::string> folderLevels;
        char* c_str = (char*)folderName.c_str();
    
        // Point to end of the string
        char* strPtr = &c_str[strlen(c_str) - 1];
    
        // Create a list of the folders which do not currently exist
        do {
            if (folderExists(c_str)) {
                break;
            }
            // Break off the last folder name, store in folderLevels list
            do {
                strPtr--;
            } while ((*strPtr != '\\') && (*strPtr != '/') && (strPtr >= c_str));
            folderLevels.push_front(string(strPtr + 1));
            strPtr[1] = 0;
        } while (strPtr >= c_str);
    
        if (_chdir(c_str)) {
            return true;
        }
    
        // Create the folders iteratively
        for (list<std::string>::iterator it = folderLevels.begin(); it != folderLevels.end(); it++) {
            if (CreateDirectory(it->c_str(), NULL) == 0) {
                return true;
            }
            _chdir(it->c_str());
        }
    
        return false;
    }
    

    The folderExists routine is as follows:

    // Return true if the folder exists, false otherwise
    bool folderExists(const char* folderName) {
        if (_access(folderName, 0) == -1) {
            //File not found
            return false;
        }
    
        DWORD attr = GetFileAttributes((LPCSTR)folderName);
        if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) {
            // File is not a directory
            return false;
        }
    
        return true;
    }
    

    An example call I tested the above functions with is as follows (and it works):

    createFolder("C:\\a\\b\\c\\d\\e\\f\\g\\h\\i\\j\\k\\l\\m\\n\\o\\p\\q\\r\\s\\t\\u\\v\\w\\x\\y\\z");
    

    This function hasn't gone through very thorough testing, and I'm not sure it yet works with other operating systems (but probably is compatible with a few modifications). I am currently using Visual Studio 2010 with Windows 7.

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

    For Windows XP and up. Expects widechar null terminated string and amount of recursive actions as parameters. Was not tested with more than 1 level yet.

    Note: Path seperators must be '\'

    bool CreateRecursiveDirectoryW(const wchar_t* filepath, const int max_level)
    {
        bool result = false;
        wchar_t path_copy[MAX_PATH] = {0};
        wcscat_s(path_copy, MAX_PATH, filepath);
        std::vector<std::wstring> path_collection;
    
        for(int level=0; PathRemoveFileSpecW(path_copy) && level < max_level; level++)
        {
            path_collection.push_back(path_copy);
        }
        for(int i=path_collection.size()-1; i >= 0; i--)
        {
            if(!PathIsDirectoryW(path_collection[i].c_str()))
                if(CreateDirectoryW(path_collection[i].c_str(), NULL))
                    result = true;
        }
        return result;
    };
    
    0 讨论(0)
  • 2020-12-01 14:18

    Here's a version that works with no external libraries, so Win32-only, and that function in all versions of Windows (including Windows CE, where I needed it):

    wchar_t *path = GetYourPathFromWherever();
    
    wchar_t folder[MAX_PATH];
    wchar_t *end;
    ZeroMemory(folder, MAX_PATH * sizeof(wchar_t));
    
    end = wcschr(path, L'\\');
    
    while(end != NULL)
    {
        wcsncpy(folder, path, end - path + 1);
        if(!CreateDirectory(folder, NULL))
        {
            DWORD err = GetLastError();
    
            if(err != ERROR_ALREADY_EXISTS)
            {
                // do whatever handling you'd like
            }
        }
        end = wcschr(++end, L'\\');
    }
    
    0 讨论(0)
  • 2020-12-01 14:18

    SHCreateDirectory function can do this. But the document states that it can get deprecated in later version of Windows.

    From MSDN

    Note This function is available through Windows XP Service Pack 2 (SP2) and Microsoft Windows Server 2003. It might be altered or unavailable in subsequent versions of Windows.

    0 讨论(0)
  • 2020-12-01 14:21
    void createFolders(const std::string &s, char delim) {
        std::stringstream ss(s);
        std::string item;
        char combinedName[50]={'\0'};
        while (std::getline(ss, item, delim)) { 
            sprintf(combinedName,"%s%s%c",combinedName,item.c_str(),delim);
            cout<<combinedName<<endl;
    
            struct stat st = {0};
                     if (stat(combinedName,&st)==-1)
                     { 
                #if REDHAT
                         mkdir(combinedName,0777);
                #else
                          CreateDirectory(combinedName,NULL);
                #endif
                     }
    
    
         }
    }
    
    0 讨论(0)
提交回复
热议问题