Home > other >  C 17 create directories automatically given a file path
C 17 create directories automatically given a file path

Time:03-29

#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;
}

I need to output some log data to some files with variable names. However, ofstream does not create directories along the way, if the path to the file doesn't exist, ofstream writes to nowhere!

What can I do to automatically create folders along a file path? The system is Ubuntu only.

CodePudding user response:

You can use this function:

bool CreateDirectoryRecuresive(const std::string & dirName)
{
    std::error_code err;
    if (!std::experimental::filesystem::create_directories(dirName, err))
    {
        if (std::experimental::filesystem::exists(dirName))
        {
            return true;    // the folder probably already existed
        }

        printf("CreateDirectoryRecuresive: FAILED to create [%s], err:%s\n", dirName.c_str(), err.message().c_str());
        return false;
    }
    return true;
}

(you can remove the experimental part if you have new enough standard library).

CodePudding user response:

According to cppreference:

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

Creates a directory for every element of p that does not already exist. If p already exists, the function does nothing. It returns true if a directory was created for the directory p resolves to, false otherwise.

What you can do is:

  1. Get the directory path in which you want to save your file to (in your example: output/folder1/data/today/).
  2. Get your file name (log.txt).
  3. Create (all of) your folder(s).
  4. Write to your file using an 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();
}
  • Related