La versione 3 di Boost Filesystem Library fornisce la funzione unique_path()
per generare un nome di percorso adatto alla creazione di un file temporaneo o di una directory.
using namespace boost::filesystem;
path ph = temp_directory_path() / unique_path();
create_directories(ph);
C++17 std::filesystem::temp_directory_path
+ generazione di numeri casuali
Ecco una soluzione C++17 pura che potrebbe essere affidabile:niente Boost o altre librerie esterne e niente mkdtemp
che è POSIX.
Ci limitiamo a ripetere numeri casuali finché non siamo in grado di creare una directory che prima non esisteva all'interno di std::filesystem::temp_directory_path
(/tmp
in Ubuntu 18.04).
Possiamo quindi rimuovere esplicitamente la directory creata con std::filesystem::remove_all
dopo che avremo finito.
Non sono sicuro che lo standard C++ lo garantisca, ma è estremamente probabile che std::filesystem::temp_directory_path
chiama mkdir
, che tenta atomicamente di creare la directory e se non ci riesce fallisce con EEXIST
, quindi non penso che possano esserci condizioni di competizione tra i chiamanti paralleli.
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 a monte.
Compila ed esegui:
g++-8 -std=c++17 -Wall -Wextra -pedantic -o main.out main.cpp -lstdc++fs
./main.out
Esempio di output:
_directory.out
temp_directory_path() = "/tmp"
create_temporary_directory() = "/tmp/106adc08ff89874c"
Per i file, vedere:Come creare un file di testo temporaneo in C++? I file sono leggermente diversi perché open
in Linux ha il O_TMPFILE
, che crea un inode anonimo che scompare automaticamente alla chiusura, quindi le API di file temporanei dedicate possono essere più efficienti utilizzandolo. Non esiste un flag analogo per mkdir
tuttavia, questa soluzione potrebbe essere ottimale.
Testato in Ubuntu 18.04.
La libreria Filesystem di Boost fornisce funzioni di directory indipendenti dalla piattaforma. Aumenterà un po' le dimensioni del tuo programma, ma l'utilizzo di Boost è spesso migliore (e spesso più facile) rispetto al rollare il tuo.
http://www.boost.org/doc/libs/1_43_0/libs/filesystem/doc/index.htm
Controlla il mkdtemp
funzione qui.