1 C++创建目录

本文将对使用C++在WindowsLinux系统上创建单级目录多级目录的普通方法进行总结,本文将不会使用C++14新增的std::filesystem的标准库方法。

1.1 在Windows/Linux上创建单级目录

1.1.1 在Windows上创建单级目录

在Windows上创建单级目录使用direct.h下的_mkdir方法,关于direct.h可参考维基百科

使用方法如下:

#include <io.h>
#include <direct.h>

int main()
{
    std::string folderPath = "E:\\database\\test\\test2\\test3";

    if (0 != _access(folderPath.c_str(), 0))
    {
        int ret = _mkdir(folderPath.c_str());
        if (ret == -1)
            return ret;
    }

    return 0;
}

1.1.2 在Linux上创建单级目录

在Linux系统上创建单级目录使用mkdir方法。

关于mkdir方法,

函数原型

int mkdir(const char *pathname, mode_t mode);

函数说明
mkdir()函数以mode方式创建一个以参数pathname命名的目录,mode定义新创建目录的权限。

函数返回值
若目录创建成功,则返回0;否则返回-1,并将错误记录到全局变量errno中。

而参数mode可设置为以下值:

  • S_IRWXU 00700权限,代表该文件所有者拥有读,写和执行操作的权限
  • S_IRUSR(S_IREAD) 00400权限,代表该文件所有者拥有可读的权限
  • S_IWUSR(S_IWRITE) 00200权限,代表该文件所有者拥有可写的权限
  • S_IXUSR(S_IEXEC) 00100权限,代表该文件所有者拥有执行的权限
  • S_IRWXG 00070权限,代表该文件用户组拥有读,写和执行操作的权限
  • S_IRGRP 00040权限,代表该文件用户组拥有可读的权限
  • S_IWGRP 00020权限,代表该文件用户组拥有可写的权限
  • S_IXGRP 00010权限,代表该文件用户组拥有执行的权限
  • S_IRWXO 00007权限,代表其他用户拥有读,写和执行操作的权限
  • S_IROTH 00004权限,代表其他用户拥有可读的权限
  • S_IWOTH 00002权限,代表其他用户拥有可写的权限
  • S_IXOTH 00001权限,代表其他用户拥有执行的权限

使用mkdir函数创建单级目录的示例代码如下,

#include <sys/stat.h>
#include <sys/types.h>
#include "stdio.h"
#include "unistd.h"
int main()
{
    std::string folderPath = "E:\\database\\test\\test2\\test3";

    if (access(folderPath.c_str(), F_OK) != 0)
    {
        int ret = mkdir(folderPath, 0755);
        if (ret == -1)
            return ret;
    }

    return 0;
}

1.2 在Windows/Linux上创建多级目录

上述1.1节中主要介绍的是创建单级目录的方式,创建单级目录成功的前提在于其父目录已经存在,如果父目录没有存在,则使用上述方式创建目录则会失败。例如,假如需要创建目录E:\\database\\test\\test2\\test3,但是他的父目录E:\\database\\test\\test2\\不存在,那么就会创建失败。所以我们需要对1.1节中的创建目录的方式进行修改和扩展,我们逐一检查指定的文件夹路径,如果某一级的文件夹路径不存在则创建该级目录,直到指定多级目录全部创建完成。

我们使用系统平台宏对上述1.1节中的方法进行了封装,使其成为一个跨Windows和Linux的创建多级目录的工具函数mkdir_in_os,该函数如下:

#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
#include <io.h>
#include <direct.h>
#elif defined(linux) || defined(__linux)
#include <sys/stat.h>
#include <sys/types.h>
#include "stdio.h"
#include "unistd.h"
#endif //


#include <iostream>

int mkdir_in_os(const std::string& dirPath)
{
    std::string dirPathCopy = dirPath;
    // 如果文件夹路径中有\\则全部替换为/
    std::string oldstr = "\\";
    std::string newstr = "/";
    for (std::string::size_type pos = 0; pos != std::string::npos; pos += newstr.length())
    {
        pos = dirPathCopy.find(oldstr, pos);
        if (pos != std::string::npos)
        {
            dirPathCopy.replace(pos, oldstr.length(), newstr);
        }
        else
        {
            break;
        }
    }

    // 创建多级目录,如果父目录不存在则创建父目录,直到指定路径的文件夹创建完成
    std::string::size_type pos = 0;
    while (pos != std::string::npos)
    {
        std::string::size_type findpos = dirPathCopy.find(newstr, pos+1);

        std::string substr = dirPathCopy.substr(0, findpos);

#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
        if (0 != _access(substr.c_str(), 0))
        {
            int ret = _mkdir(substr.c_str());
            if (ret == -1)
                return ret;
        }
#elif defined(linux) || defined(__linux)
        if (access(substr.c_str(), F_OK) != 0)
        {
            int ret = mkdir(substr, 0755);
            if (ret == -1)
                return ret;
        }

#endif //
        std::cout << substr << std::endl;

        pos = findpos;
    }

    return 0;
}

使用示例如下:

#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
#include <io.h>
#include <direct.h>
#elif defined(linux) || defined(__linux)
#include <sys/stat.h>
#include <sys/types.h>
#include "stdio.h"
#include "unistd.h"
#endif // 


#include <iostream>

int mkdir_in_os(const std::string& dirPath)
{
    std::string dirPathCopy = dirPath;
    // 如果文件夹路径中有\\则全部替换为/
    std::string oldstr = "\\";
    std::string newstr = "/";
    for (std::string::size_type pos = 0; pos != std::string::npos; pos += newstr.length())
    {
        pos = dirPathCopy.find(oldstr, pos);
        if (pos != std::string::npos)
        {
            dirPathCopy.replace(pos, oldstr.length(), newstr);
        }
        else
        {
            break;
        }
    }

    // 创建多级目录,如果父目录不存在则创建父目录,直到指定路径的文件夹创建完成
    std::string::size_type pos = 0;
    while (pos != std::string::npos)
    {
        std::string::size_type findpos = dirPathCopy.find(newstr, pos+1);

        std::string substr = dirPathCopy.substr(0, findpos);

#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
        if (0 != _access(substr.c_str(), 0))
        {
            int ret = _mkdir(substr.c_str());
            if (ret == -1)
                return ret;
        }
#elif defined(linux) || defined(__linux)
        if (access(substr.c_str(), F_OK) != 0)
        {
            int ret = mkdir(substr, 0755);
            if (ret == -1)
                return ret;
        }

#endif // 
        std::cout << substr << std::endl;

        pos = findpos;
    }

    return 0;
}


int main()
{
    std::string folderPath = "E:\\database\\test\\test2\\test3";

    mkdir_in_os(folderPath.c_str());

    return 0;
}