Ich möchte den schnellsten Weg finden, um zu überprüfen, ob eine Datei in Standard C ++ 11, C ++ oder C vorhanden ist. Ich habe Tausende von Dateien und bevor ich etwas daran mache, muss ich überprüfen, ob alle vorhanden sind. Was kann ich anstelle /* SOMETHING */
der folgenden Funktion schreiben ?
inline bool exist(const std::string& name)
{
/* SOMETHING */
}
boost::filesystem
scheint zu verwendenstat()
. (Vorausgesetzt aus der Dokumentation.) Ich glaube nicht, dass Sie für FS-Anrufe viel schneller arbeiten können. Der Weg, um das, was Sie tun, schnell zu machen, besteht darin, "Tausende von Dateien nicht anzusehen".git push
wahrscheinlich nicht die Mühe, sicherzustellen, dass Sie den Arbeitsbaum nach der ersten schmutzigen Prüfung nicht berühren.Antworten:
Nun, ich habe ein Testprogramm zusammengestellt, das jede dieser Methoden 100.000 Mal ausführte, je zur Hälfte für vorhandene Dateien und zur Hälfte für nicht vorhandene Dateien.
Ergebnisse für die Gesamtzeit zum Ausführen der 100.000 Anrufe, gemittelt über 5 Läufe,
Die
stat()
Funktion bot die beste Leistung auf meinem System (Linux, kompiliert mitg++
), wobei ein Standardaufruffopen
die beste Wahl ist, wenn Sie aus irgendeinem Grund die Verwendung von POSIX-Funktionen ablehnen.quelle
stat()
scheint auf Existenz zu prüfen.f.close()
da f am Ende der Funktion den Gültigkeitsbereich verlässt . Soreturn f.good()
könnte der Ersatz -if
Block?Anmerkung: In C ++ 14 und sobald das Dateisystem TS fertiggestellt und übernommen ist, besteht die Lösung darin, Folgendes zu verwenden:
und seit C ++ 17 nur:
quelle
std::tr2::sys::exists("helloworld.txt");
std::exists
, dass dies nicht der Fall ist, was ziemlich verwirrend wäre (denken Sie: existiert in einem STL-Container wie einem Set).#include <experimental/filesystem> bool file_exists(std::string fn) { std::experimental::filesystem::exists("helloworld.txt"); }
#include <experimental/filesystem>
Ich benutze diesen Code, er funktioniert bei mir bisher einwandfrei. Dies nutzt nicht viele ausgefallene Funktionen von C ++:
quelle
ifstream
Destruktor wird beim Beenden aufgerufenis_file_exist
und schließt den Stream.return std::ifstream(fileName);
Dies hängt davon ab, wo sich die Dateien befinden. Wenn sich beispielsweise alle im selben Verzeichnis befinden sollen, können Sie alle Verzeichniseinträge in eine Hash-Tabelle einlesen und dann alle Namen mit der Hash-Tabelle vergleichen. Dies könnte schneller auf manchen Systemen 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 dies der einzige Weg ist (eine Datei ist möglicherweise vorhanden, aber nicht zu öffnen, aber Sie möchten sie wahrscheinlich wirklich öffnen, wenn Sie dies tun müssen "etwas darauf tun"). C ++, POSIX und Windows bieten zusätzliche Optionen.Lassen Sie mich, während ich dabei bin, 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 Sie eine Annahme über die Lösung treffen ... ein Fall des XY-Problems . Sie sagen auch "in Standard c ++ 11 (oder) c ++ (oder) c" ... die alle unterschiedlich sind, und dies steht auch im Widerspruch zu Ihrer Anforderung an die Geschwindigkeit ... die schnellste Lösung würde darin bestehen, den Code an das 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, die nicht Standard C oder C ++ sind.
quelle
Für diejenigen, die Boost mögen:
quelle
Ohne andere Bibliotheken zu verwenden, verwende ich gerne das folgende Code-Snippet:
Dies funktioniert plattformübergreifend für Windows- und POSIX-kompatible Systeme.
quelle
unistd.h
auch enthalten kann. Vielleicht sollte der erste#ifdef
Windows-spezifisch sein?Wie von PherricOxide vorgeschlagen, jedoch in C.
quelle
quelle
close()
nicht erforderlich ist.Weitere 3 Optionen unter Windows:
1
2
3
quelle
GetFileAttributes
Version ist im Grunde die kanonische Methode, um dies in Windows zu tun.Sie können auch tun
bool b = std::ifstream('filename').good();
. Ohne die Verzweigungsanweisungen (wie wenn) muss es schneller arbeiten, da es tausende Male aufgerufen werden muss.quelle
Wenn Sie zwischen einer Datei und einem Verzeichnis unterscheiden müssen, beachten Sie Folgendes: Beide verwenden stat, das schnellste Standardwerkzeug, wie von PherricOxide gezeigt:
quelle
Ich brauche eine schnelle Funktion, die überprüfen kann, ob eine Datei vorhanden ist oder nicht, und die Antwort von PherricOxide ist fast das, was ich brauche, außer dass sie die Leistung von boost :: filesystem :: exist und offenen Funktionen nicht vergleicht. An den Benchmark-Ergebnissen können wir leicht erkennen, dass:
Die Verwendung der Statistikfunktion ist der schnellste Weg, um zu überprüfen, ob eine Datei vorhanden ist. Beachten Sie, dass meine Ergebnisse mit denen der Antwort von PherricOxide übereinstimmen.
Die Leistung der Funktion boost :: filesystem :: existiert kommt der der Funktion stat sehr nahe und ist auch portabel. Ich würde diese Lösung empfehlen, wenn Boost-Bibliotheken über Ihren Code zugänglich sind.
Benchmark-Ergebnisse mit Linux-Kernel 4.17.0 und gcc-7.3:
Unten ist mein Benchmark-Code:
quelle
Sie können verwendet werden
std::ifstream
, funcion wieis_open
,fail
zum Beispiel , wie unten Code (der cout „offen“ bedeutet Datei existiert oder nicht):zitiert aus dieser Antwort
quelle
Wo
R
ist deine Abfolge von pfadartigen Dingen undexists()
ist von der zukünftigen Standard- oder aktuellen Boost. Wenn Sie Ihre eigenen rollen, halten Sie es einfach,Die verzweigte Lösung ist nicht absolut schrecklich und verschlingt keine Dateideskriptoren.
quelle
PathFileExists
ist aufMAX_PATH
(260) Zeichen begrenzt;GetFileAttributes
hat diese Einschränkung nicht.GetFileAttributes
ist ebenfalls auf MAX_PATH beschränkt. In den Dokumenten wird eine Problemumgehung beschrieben, wenn Sie absolute Pfade und Unicode verwenden und dem Pfadnamen eine spezielle Präfixzeichenfolge voranstellen. Ich denke, wir haben es sowieso mit den Windows-spezifischen Antworten zu tun.GetFileAttributesW
hat nicht die Einschränkung.In C ++ 17:
quelle
Mit MFC ist Folgendes möglich
Wo
FileName
ist eine Zeichenfolge, die die Datei darstellt, die Sie auf Existenz prüfen?quelle
Es gibt nur einen schnelleren Weg, um zu überprüfen, ob die Datei vorhanden ist, und wenn Sie die Berechtigung zum Lesen haben, ist die Verwendung der C-Sprache schneller und kann auch in jeder Version in C ++ verwendet werden
Lösung : In C gibt es eine Bibliothek errno.h mit einer externen (globalen) Ganzzahlvariablen namens errno, die eine Zahl enthält, mit der der Fehlertyp erkannt werden kann
quelle
Obwohl es mehrere Möglichkeiten gibt, dies zu tun, besteht die effizienteste Lösung für Ihr Problem wahrscheinlich darin, eine der vordefinierten Methoden des fstream wie good () zu verwenden . Mit dieser Methode können Sie überprüfen, ob die von Ihnen angegebene Datei vorhanden ist oder nicht.
Ich hoffe, Sie finden das nützlich.
quelle