Как создать файл и папки по пути к нему
Есть файл:
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 шт):
Грустно, что нельзя использовать что-то кроме С++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. Рекурсия особо не нужна, если каталог уже есть - попытка его создать к неприятностям не приведет...
Отвечу по поводу создания нескольких директорий, вложенных друг в друга, à 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;
}