La version 3 de Boost Filesystem Library fournit la fonction unique_path()
pour générer un nom de chemin adapté à la création d'un fichier ou d'un répertoire temporaire.
using namespace boost::filesystem;
path ph = temp_directory_path() / unique_path();
create_directories(ph);
C++17 std::filesystem::temp_directory_path
+ génération de nombres aléatoires
Voici une solution purement C++17 qui pourrait être fiable :pas de Boost ou d'autres bibliothèques externes et pas de mkdtemp
qui est POSIX.
Nous faisons juste une boucle sur des nombres aléatoires jusqu'à ce que nous puissions créer un répertoire qui n'existait pas auparavant dans std::filesystem::temp_directory_path
(/tmp
dans Ubuntu 18.04).
On peut alors supprimer explicitement le répertoire créé avec std::filesystem::remove_all
une fois que nous en aurons terminé.
Je ne suis pas sûr que la norme C++ le garantisse, mais il est extrêmement probable que std::filesystem::temp_directory_path
appelle mkdir
, qui essaie atomiquement de créer le répertoire et s'il ne peut pas échouer avec EEXIST
, donc je ne pense pas qu'il puisse y avoir des conditions de concurrence entre les appelants parallèles.
main.cpp
#include <exception>
#include <fstream>
#include <iostream>
#include <random>
#include <sstream>
#include <filesystem>
std::filesystem::path create_temporary_directory(
unsigned long long max_tries = 1000) {
auto tmp_dir = std::filesystem::temp_directory_path();
unsigned long long i = 0;
std::random_device dev;
std::mt19937 prng(dev());
std::uniform_int_distribution<uint64_t> rand(0);
std::filesystem::path path;
while (true) {
std::stringstream ss;
ss << std::hex << rand(prng);
path = tmp_dir / ss.str();
// true if the directory was created.
if (std::filesystem::create_directory(path)) {
break;
}
if (i == max_tries) {
throw std::runtime_error("could not find non-existing directory");
}
i++;
}
return path;
}
int main() {
auto tmpdir = create_temporary_directory();
std::cout << "create_temporary_directory() = "
<< tmpdir
<< std::endl;
// Use our temporary directory: create a file
// in it and write to it.
std::ofstream ofs(tmpdir / "myfile");
ofs << "asdf\nqwer\n";
ofs.close();
// Remove the directory and its contents.
std::filesystem::remove_all(tmpdir);
}
GitHub en amont.
Compiler et exécuter :
g++-8 -std=c++17 -Wall -Wextra -pedantic -o main.out main.cpp -lstdc++fs
./main.out
Exemple de sortie :
_directory.out
temp_directory_path() = "/tmp"
create_temporary_directory() = "/tmp/106adc08ff89874c"
Pour les fichiers, voir :Comment créer un fichier texte temporaire en C++ ? Les fichiers sont un peu différents car open
sous Linux a le O_TMPFILE
, qui crée un inode anonyme qui disparaît automatiquement à la fermeture, de sorte que les API de fichiers temporaires dédiées peuvent être plus efficaces en utilisant cela. Il n'y a pas d'indicateur analogue pour mkdir
cependant, cette solution pourrait être optimale.
Testé dans Ubuntu 18.04.
La bibliothèque Filesystem de Boost fournit des fonctions de répertoire indépendantes de la plate-forme. Cela augmentera un peu la taille de votre programme, mais utiliser Boost est souvent mieux (et souvent plus facile) que de lancer le vôtre.
http://www.boost.org/doc/libs/1_43_0/libs/filesystem/doc/index.htm
Vérifiez le mkdtemp
fonction ici.