
Vinzenz
Ich würde gerne den schnellsten Weg finden, um zu überprüfen, ob eine Datei in Standard-C++ 11, 14, 17 oder C existiert. Ich habe Tausende von Dateien und bevor ich etwas mit ihnen mache, muss ich überprüfen, ob sie alle existieren. Was kann ich stattdessen schreiben /* SOMETHING */
in der folgenden Funktion?
inline bool exist(const std::string& name)
{
/* SOMETHING */
}

PherricOxide
Nun, ich habe ein Testprogramm zusammengestellt, das jede dieser Methoden 100.000 Mal ausgeführt hat, halb für Dateien, die existierten, und halb für Dateien, die nicht existierten.
#include <sys/stat.h>
#include <unistd.h>
#include <string>
#include <fstream>
inline bool exists_test0 (const std::string& name) {
ifstream f(name.c_str());
return f.good();
}
inline bool exists_test1 (const std::string& name) {
if (FILE *file = fopen(name.c_str(), "r")) {
fclose(file);
return true;
} else {
return false;
}
}
inline bool exists_test2 (const std::string& name) {
return ( access( name.c_str(), F_OK ) != -1 );
}
inline bool exists_test3 (const std::string& name) {
struct stat buffer;
return (stat (name.c_str(), &buffer) == 0);
}
Ergebnisse für die Gesamtzeit zum Durchführen der 100.000 Aufrufe, gemittelt über 5 Läufe,
Methode |
Zeit |
exists_test0 (wenn stream) |
0,485 s |
exists_test1 (DATEI föffnen) |
0,302 s |
exists_test2 (Posix-Zugriff()) |
0,202 s |
exists_test3 (Posix-Statistik()) |
0,134 s |
Die stat()
Funktion lieferte die beste Leistung auf meinem System (Linux, kompiliert mit g++
), mit einem Standard fopen
call ist die beste Wahl, wenn Sie sich aus irgendeinem Grund weigern, POSIX-Funktionen zu verwenden.

Vinzenz
Bemerkung: in C++14 und sobald die Dateisystem TS fertig gestellt und angenommen wird, wird die Lösung sein:
std::experimental::filesystem::exists("helloworld.txt");
und seit C++17 nur noch:
std::filesystem::exists("helloworld.txt");
Ich verwende dieses Stück Code, es funktioniert bisher bei mir. Dies verwendet nicht viele ausgefallene Funktionen von C++:
bool is_file_exist(const char *fileName)
{
std::ifstream infile(fileName);
return infile.good();
}

Anhoppe
Für diejenigen, die Boost mögen:
boost::filesystem::exists(fileName)
oder seit ISO C++17:
std::filesystem::exists(fileName)

Jim Balter
Es hängt davon ab, wo sich die Dateien befinden. Sollen sie beispielsweise alle im selben Verzeichnis liegen, können Sie alle Verzeichniseinträge in eine Hash-Tabelle einlesen und dann alle Namen mit der Hash-Tabelle vergleichen. Dies könnte auf einigen Systemen schneller sein, als jede Datei einzeln zu prüfen. Der schnellste Weg, jede Datei einzeln zu überprüfen, hängt von Ihrem System ab … wenn Sie ANSI C schreiben, ist der schnellste Weg fopen
weil es der einzige Weg ist (eine Datei kann existieren, aber nicht geöffnet werden, aber Sie möchten wahrscheinlich wirklich öffnen können, wenn Sie “etwas damit machen müssen”). C++, POSIX, Windows bieten alle zusätzliche Optionen.
Wenn ich schon dabei bin, lassen Sie mich auf einige Probleme mit Ihrer Frage hinweisen. Sie sagen, dass Sie den schnellsten Weg wollen und dass Sie Tausende von Dateien haben, aber dann fragen Sie nach dem Code für eine Funktion zum Testen einer einzelnen Datei (und diese Funktion ist nur in C++ gültig, nicht in C). Dies widerspricht Ihren Anforderungen, indem eine Annahme über die Lösung getroffen wird … ein Fall von das XY-Problem. Sie sagen auch “in Standard-c ++ 11 (oder) c ++ (oder) c” … die alle unterschiedlich sind, und dies entspricht auch nicht Ihrer Geschwindigkeitsanforderung … die schnellste Lösung würde darin bestehen, den Code an die anzupassen Zielsystem. Die Inkonsistenz in der Frage wird durch die Tatsache hervorgehoben, dass Sie eine Antwort akzeptiert haben, die systemabhängige Lösungen enthält und nicht Standard-C oder C++ ist.

Alexander Huszagh
Ohne andere Bibliotheken zu verwenden, verwende ich gerne das folgende Code-Snippet:
#ifdef _WIN32
#include <io.h>
#define access _access_s
#else
#include <unistd.h>
#endif
bool FileExists( const std::string &Filename )
{
return access( Filename.c_str(), 0 ) == 0;
}
Dies funktioniert plattformübergreifend für Windows- und POSIX-kompatible Systeme.

O’Neil
Dasselbe wie von PherricOxide vorgeschlagen, aber in C
#include <sys/stat.h>
int exist(const char *name)
{
struct stat buffer;
return (stat (name, &buffer) == 0);
}
9871500cookie-checkDer schnellste Weg, um zu überprüfen, ob eine Datei mit Standard-C++/C++11,14,17/C vorhanden ist?yes
boost::filesystem
scheint zu gebrauchenstat()
. (Ausgehend von der Dokumentation.) Ich glaube nicht, dass Sie für FS-Aufrufe viel schneller arbeiten können. Der Weg, um das, was Sie tun, schnell zu machen, besteht darin, „das Betrachten von Tausenden von Dateien zu vermeiden“.– Millielch
8. Oktober 2012 um 1:15 Uhr
TOCTOU Frage: Woher wissen Sie, dass die Datei zwischen Ihrer Prüfung vonexists() und Ihrer „etwas dagegen tun“?
– Pilkrähe
8. Oktober 2012 um 1:16 Uhr
@pilcrow Guter Punkt, aber es gibt eine ziemlich breite Palette von Anwendungen, die nicht so viel Korrektheit erfordern. Z.B
git push
macht sich wahrscheinlich nicht die Mühe, sicherzustellen, dass Sie den Arbeitsbaum nach der anfänglichen schmutzigen Prüfung nicht berühren.– Millielch
8. Oktober 2012 um 1:27 Uhr
„Mir fällt keine C/C++-Implementierung ein, die das nicht hätte“ – Windows bietet keine POSIX-Umgebung.
– Jim Balter
8. Oktober 2012 um 1:58 Uhr
Mögliches Duplikat von std::ofstream, prüfen Sie vor dem Schreiben, ob die Datei existiert
– MDXF
27. Februar 2017 um 4:17 Uhr