642 Stimmen

Der schnellste Weg, um zu prüfen, ob eine Datei mit Standard-C++/C++11,14,17/C existiert?

Ich möchte den schnellsten Weg finden, um zu prü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 prüfen, ob sie alle existieren. Was kann ich anstelle von /* SOMETHING */ in der folgenden Funktion?

inline bool exist(const std::string& name)
{
    /* SOMETHING */
}

1027voto

PherricOxide Punkte 14899

Ich habe ein Testprogramm erstellt, das jede dieser Methoden 100.000 Mal ausgeführt hat, zur Hälfte mit Dateien, die es gab, und zur Hälfte mit Dateien, die es nicht gab.

#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 zur Ausführung der 100.000 Aufrufe, gemittelt über 5 Läufe,

Methode

Zeit

exists_test0 (ifstream)

0.485s

exists_test1 (DATEI fopen)

0.302s

exists_test2 (posix access())

0.202s

exists_test3 (posix stat())

0.134s

En stat() Funktion lieferte die beste Leistung auf meinem System (Linux, kompiliert mit g++ ), mit einem Standard fopen Aufruf ist die beste Lösung, wenn Sie sich aus irgendeinem Grund weigern, POSIX-Funktionen zu verwenden.

299voto

Vincent Punkte 55305

Bemerkung: In C++14 und sobald die Dateisystem TS fertiggestellt und angenommen werden, wird die Lösung darin bestehen, sie zu verwenden:

std::experimental::filesystem::exists("helloworld.txt");

und erst seit C++17:

std::filesystem::exists("helloworld.txt");

142voto

harryngh Punkte 1689

Ich verwende diesen Code, der bei mir bis jetzt gut funktioniert. Es werden nicht viele ausgefallene Funktionen von C++ verwendet:

bool is_file_exist(const char *fileName)
{
    std::ifstream infile(fileName);
    return infile.good();
}

54voto

anhoppe Punkte 3769

Für diejenigen, die Boost mögen:

 boost::filesystem::exists(fileName)

oder, seit ISO C++17:

 std::filesystem::exists(fileName)

30voto

Jim Balter Punkte 15501

Das hängt davon ab, wo sich die Dateien befinden. Wenn sie 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 abgleichen. Diese könnte auf manchen Systemen schneller sein, als jede Datei einzeln zu prüfen. Der schnellste Weg, jede Datei einzeln zu prüfen, hängt von Ihrem System ab ... wenn Sie in ANSI C schreiben, ist der schnellste Weg fopen weil es die einzige Möglichkeit ist (eine Datei kann zwar existieren, aber nicht geöffnet werden, aber Sie wollen wahrscheinlich wirklich, dass sie geöffnet werden kann, wenn Sie "etwas mit ihr machen" wollen). C++, POSIX und Windows bieten alle zusätzliche Optionen.

Wenn ich schon dabei bin, möchte ich 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 einzigen Datei (und diese Funktion ist nur in C++ gültig, nicht in C). Dies widerspricht Ihren Anforderungen, da Sie eine Annahme über die Lösung machen ... ein Fall von das XY-Problem . Sie sagen auch "in standard c++11(oder)c++(oder)c" ... die alle unterschiedlich sind, und dies ist auch mit Ihrer Anforderung an die Geschwindigkeit unvereinbar ... die schnellste Lösung würde die Anpassung des Codes an das Zielsystem beinhalten. Die Ungereimtheit der Frage wird durch die Tatsache unterstrichen, dass Sie eine Antwort akzeptiert haben, die Lösungen bietet, die systemabhängig sind und nicht dem Standard C oder C++ entsprechen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X