C++17 根据给定的文件路径自动创建目录

问题描述 投票:0回答:2
#include <iostream>
#include <fstream>
using namespace std;
    
int main()
{
    ofstream fo("output/folder1/data/today/log.txt");
    fo << "Hello world\n";
    fo.close();
    
    return 0;
}

我需要将一些日志数据输出到一些带有变量名称的文件中。但是,

ofstream
不会一路创建目录,如果文件的路径不存在,
ofstream
不会写入任何地方!

如何才能沿着文件路径自动创建文件夹?系统仅限Ubuntu。

c++ file ubuntu filesystems filepath
2个回答
5
投票

您可以使用此功能来实现,如下所示。

它使用

std::filesystem::create_directories
std::filesystem::exists

#include <string>
#include <filesystem>

// Returns:
//   true upon success.
//   false upon failure, and set the std::error_code & err accordingly.
bool CreateDirectoryRecursive(std::string const & dirName, std::error_code & err)
{
    err.clear();
    if (!std::filesystem::create_directories(dirName, err))
    {
        if (std::filesystem::exists(dirName))
        {
            // The folder already exists:
            err.clear();
            return true;    
        }
        return false;
    }
    return true;
}

使用示例:

#include <iostream>

int main() 
{
    std::error_code err;
    if (!CreateDirectoryRecursive("/tmp/a/b/c", err))
    {
        // Report the error:
        std::cout << "CreateDirectoryRecursive FAILED, err: " << err.message() << std::endl;
    }
}

注:

<filesystem>
自 c++-17 起可用。
在此之前,它可以通过
<experimental/filesystem>
标头在许多编译器中使用。


3
投票

根据cppreference

bool create_directories(const std::filesystem::path& p);

p
中尚不存在的每个元素创建一个目录。如果
p
已经存在,则该函数不执行任何操作。如果为目录
true
解析为创建了目录,则返回
p
,否则返回
false

你能做的是:

  1. 获取要保存文件的目录路径(在您的示例中:
    output/folder1/data/today/
    )。
  2. 获取您的文件名 (
    log.txt
    )。
  3. 创建(全部)您的文件夹。
  4. 使用
    std::fstream
    写入您的文件。
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <fstream>
#include <filesystem>

namespace fs = std::filesystem;

// Split a string separated by sep into a vector
std::vector<std::string> split(const std::string& str, const char sep)
{
    std::string token; 
    std::stringstream ss(str);
    std::vector<std::string> tokens;
    
    while (std::getline(ss, token, sep)) {
        tokens.push_back(token);
    }
    
    return tokens;
}

int main()
{
    std::string path = "output/folder1/data/today/log.txt";
    
    std::vector<std::string> dirs = split(path, '/');
    
    if (dirs.empty())
        return 1;
    
    std::string tmp = "./"; // Current dir
    for (auto it = dirs.begin(); it != std::prev(dirs.end()); ++it)
        tmp += *it + '/';
    
    fs::create_directories(tmp);
    
    std::ofstream os(tmp + dirs.back());
    os << "Some text...\n";
    os.close();
}
© www.soinside.com 2019 - 2024. All rights reserved.