Version 3 der Boost-Dateisystembibliothek bietet die Funktion unique_path()
zum Generieren eines Pfadnamens, der zum Erstellen einer temporären Datei oder eines temporären Verzeichnisses geeignet ist.
using namespace boost::filesystem;
path ph = temp_directory_path() / unique_path();
create_directories(ph);
C++17 std::filesystem::temp_directory_path
+ Generierung von Zufallszahlen
Hier ist eine reine C++17-Lösung, die zuverlässig sein könnte:kein Boost oder andere externe Bibliotheken und kein mkdtemp
das ist POSIX.
Wir durchlaufen einfach Zufallszahlen, bis wir in der Lage sind, ein Verzeichnis zu erstellen, das vorher nicht in std::filesystem::temp_directory_path
existierte (/tmp
in Ubuntu 18.04).
Das erstellte Verzeichnis können wir dann mit std::filesystem::remove_all
explizit entfernen nachdem wir damit fertig sind.
Ich bin mir nicht sicher, ob der C++-Standard dies garantiert, aber es ist sehr wahrscheinlich, dass std::filesystem::temp_directory_path
ruft mkdir
auf , die atomar versucht, das Verzeichnis zu erstellen, und wenn dies nicht möglich ist, mit EEXIST
fehlschlägt , also glaube ich nicht, dass es zwischen parallelen Callern Race-Conditions geben kann.
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-Upstream.
Kompilieren und ausführen:
g++-8 -std=c++17 -Wall -Wextra -pedantic -o main.out main.cpp -lstdc++fs
./main.out
Beispielausgabe:
_directory.out
temp_directory_path() = "/tmp"
create_temporary_directory() = "/tmp/106adc08ff89874c"
Für Dateien siehe:Wie erstelle ich eine temporäre Textdatei in C++? Dateien sind etwas anders, weil open
hat unter Linux den O_TMPFILE
, wodurch ein anonymer Inode erstellt wird, der beim Schließen automatisch verschwindet, sodass dedizierte APIs für temporäre Dateien dadurch effizienter sein können. Es gibt kein analoges Flag für mkdir
jedoch könnte diese Lösung optimal sein.
Getestet in Ubuntu 18.04.
Die Dateisystembibliothek von Boost bietet plattformunabhängige Verzeichnisfunktionen. Es wird Ihre Programmgröße ein wenig erhöhen, aber die Verwendung von Boost ist oft besser (und oft einfacher), als Ihr eigenes zu erstellen.
http://www.boost.org/doc/libs/1_43_0/libs/filesystem/doc/index.htm
Überprüfen Sie den mkdtemp
Funktion hier.