如何在Win32中递归创建文件夹?

pau*_*doo 35 c++ directory winapi

我正在尝试创建一个带有目录(C:\foo\bar,或..\foo\bar\..\baz,或\\someserver\foo\bar)名称的函数,并根据需要创建目录,以便创建整个路径.

我自己尝试了一个非常天真的实现,它似乎是一个字符串处理的噩梦.有/vs \,有网络共享的特殊情况开始\\(也不能尝试mkdir()路径的前两个级别,即机器名和共享名),并且存在\.\可以存在的类型废话在一条路上.

在C++中是否存在一种简单的方法?

Fre*_*abe 48

如果您不需要支持Windows 2000之前的Windows版本,则可以使用SHCreateDirectoryEx函数.考虑一下:

int createDirectoryRecursively( LPCTSTR path )
{
    return SHCreateDirectoryEx( NULL, path, NULL );
}

// ...
if ( createDirectoryRecursively( T("C:\\Foo\\Bar\\Baz") ) == ERROR_SUCCESS ) {
   // Bingo!
} 
Run Code Online (Sandbox Code Playgroud)

如果使用这样的shell32.dll API成为一个问题,您总是可以使用其他东西(可能是手动连线循环)重新实现上面的createDirectoryRecursively函数.


cta*_*cke 11

这是一个没有外部库的版本,因此只支持Win32,并且在所有版本的Windows中都有该功能(包括Windows CE,我需要它):

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'\\');
}
Run Code Online (Sandbox Code Playgroud)

  • 它旨在采用完全限定的文件路径,并且将确保目标文件夹存在。如果您只想给它传递一个文件夹路径,那么可以,它将需要进一步的工作 (2认同)

Jon*_*cht 7

这是我编写的一个函数,它迭代地创建了一个文件夹树.这是主要功能:

#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;
}
Run Code Online (Sandbox Code Playgroud)

folderExists程序如下:

// 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;
}
Run Code Online (Sandbox Code Playgroud)

我测试上述函数的示例调用如下(并且它可以工作):

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");
Run Code Online (Sandbox Code Playgroud)

此功能尚未经过非常彻底的测试,我不确定它是否适用于其他操作系统(但可能与一些修改兼容).我现在使用的Visual Studio 2010Windows 7.


Nat*_*eed 6

使用 C++17,这可以很容易地使用std::filesystem::create_directories().

例子:

#include <filesystem>
...

const char* path = "C:\\foo\\bar";
std::filesystem::create_directories(path);
Run Code Online (Sandbox Code Playgroud)


Aam*_*mir 5

SHCreateDirectory函数可以做到这一点.但该文档声明它可以在更高版本的Windows中被弃用.

来自MSDN

注意此功能可通过Windows XP Service Pack 2(SP2)和Microsoft Windows Server 2003获得.它可能会在后续版本的Windows中更改或不可用.