Как создать файл и папки по пути к нему

Есть файл:

const std::string logFile = "log.txt";

Есть путь к нему:

const std::string logPath = "Logs/tmp/" 

Как создать папки по пути к файлу, если из нет.
А также как создать файл, если его нет, а если есть - дописать в его конец.

Также, поскольку я использую C++11, я не могу использовать std::filesystem или std::experimental.


У меня сейчас так:

#ifndef DEBUGGER_HPP
#define DEBUGGER_HPP

#include <ctime>
#include <fstream>
#include <iostream>



#include "../Main/Settings.hpp"

namespace Debugger
{

    //
    void PrintDebug(const std::string input){
        if (Settings::settings_DebugMode >= 2){

            // Add current datetime
            auto seconds = time(NULL);
            auto* timeinfo = localtime(&seconds);

            std::string result = "[DEBUG] [ ";
            result += asctime(timeinfo);
            result.erase(result.rfind('\n'), 1);
            result += " ] " + input + '\n';

            if (Settings::settings_LogPath == "console"){
                std::cout << result;
            } else {

                // Create folder if it doesn't exist
                for(std::string::size_type pos = 0; (pos = Settings::settings_LogPath.find('/',pos+1)) != std::string::npos;)
                {
                    mkdir(Settings::settings_LogPath.substr(0,pos).c_str());
                }

                // Create logFile
                std::ofstream logFile;
                logFile.open("log.txt", std::ios::app);
                logFile << result;
                logFile.close();
            }
        }
    }

}

#endif // DEBUGGER_HPP

Ответы (2 шт):

Автор решения: Harry

Грустно, что нельзя использовать что-то кроме С++11.

Тогда посоветовал бы разбивать путь на составные куски по слешу, и использовать mkdir для покусочного :) создания пути (насколько я помню, длинные вложенные каталоги он не создает - типа, log/test не создаст, если нет log).

Ну, а когда путь есть и вы в этом убедились - обычные функции для работы с файлами. Например,

ofstream of("data",ios::app);
of << "random string" << endl;

Если файла нет - он будет создан, если есть - будет выполнена дозапись в его конец.

Разбивать на части? Да хоть так:

string logPath = "My/Long/Log/path/";
for(string::size_type pos = 0; (pos = logPath.find('/',pos+1)) != string::npos;)
{
    cout << "mkdir(" << logPath.substr(0,pos).c_str() << ")\n";
}

Понятно, что вместо вывода строки надо использовать mkdir. Рекурсия особо не нужна, если каталог уже есть - попытка его создать к неприятностям не приведет...

→ Ссылка
Автор решения: Danny

Отвечу по поводу создания нескольких директорий, вложенных друг в друга, à la mkdir -p. Это популярный запрос, как выяснилось. Есть программы, написанные для создания директорий рекурсивно, например здесь: http://mylinuxtechcorner.blogspot.com/2012/09/c-version-for-mkdir-p.html

Привожу код оттуда:

int createPath( mode_t mode, const std::string& rootPath, std::string& path )
{
    struct stat st;

    for( std::string::iterator iter = path.begin() ; iter != path.end(); )
    {
         std::string::iterator newIter = std::find( iter, path.end(), '/' );
         std::string newPath = rootPath + "/" + std::string( path.begin(), newIter);

         if( stat( newPath.c_str(), &st) != 0)
         {           
             if( mkdir( newPath.c_str(), mode) != 0 && errno != EEXIST )
             {
                std::cout << "cannot create folder [" << newPath << "] : " << strerror(errno) << std::endl;
                return -1;
             }
         }
         else
            if( !S_ISDIR(st.st_mode) )
             {
                 errno = ENOTDIR;
                 std:: cout << "path [" << newPath << "] not a dir " << std::endl;
                 return -1;
             }
             else
                 std::cout << "path [" << newPath << "] already exists " << std::endl;


         iter = newIter;
         if( newIter != path.end() )
             ++ iter;
    }
    return 0;
}


int main() {

    std::string path = "ionut/AAA/BBB";
    createPath(0777, "/home", path);
    return 0;
}
→ Ссылка