Wie kann am besten überprüft werden, ob eine Datei in C ++ vorhanden ist? (plattformübergreifend)

97

Ich habe die Antworten für Wie kann ich am besten überprüfen, ob eine Datei in C vorhanden ist? (plattformübergreifend) , aber ich frage mich, ob es einen besseren Weg gibt, dies mit Standard-C ++ - Bibliotheken zu tun. Am besten ohne zu versuchen, die Datei überhaupt zu öffnen.

Beide statund accesssind so gut wie unaussprechlich. Was soll ich verwenden #include, um diese zu verwenden?

c0m4
quelle
<io.h> für den Zugriff (was tatsächlich _access sein könnte).
Rob
Ja, wie darauf hingewiesen wurde.
c0m4

Antworten:

170

Verwenden Sie boost :: filesystem :

#include <boost/filesystem.hpp>

if ( !boost::filesystem::exists( "myfile.txt" ) )
{
  std::cout << "Can't find my file!" << std::endl;
}
Andreas Magnusson
quelle
68
Es scheint ein bisschen ein hazzle zu sein , eine große Dritten Bibliothek zu installieren , etwas zu tun , das sollte einfach sein
c0m4
89
Boost ist eine Bibliothek, in der ein Großteil dessen entwickelt wird, was später Teil der C ++ - Standardbibliothek sein wird. Viele der Personen, die mit Boost zu tun haben, sind mit dem C ++ - Standard befasst. Boost ist also nicht irgendeine Bibliothek von Drittanbietern. Wenn Sie in C ++ programmieren, sollten Sie Boost installiert haben!
Andreas Magnusson
Ich erinnere mich, dass b :: fs :: exist "true" für nicht vorhandene Dateien auf Netzwerkfreigaben zurückgibt: "\\ machine \ share \ this_file_doesnt_exist" => true. Das letzte Mal, als ich nachgesehen habe, war Boost 1.33, seien Sie vorsichtig ...
Rlerallut
Wenn Ihr Compiler mit einer tr1-Implementierung geliefert wird, müssen Sie Boost nicht einmal installieren. Es wird im std :: tr1 :: Dateisystem sein
Nemanja Trifunovic
1
Eigentlich hat ASFAIK TR1 nicht gemacht, wird aber zu einem späteren Zeitpunkt hinzugefügt. Ich habe auch im offiziellen TR1-Entwurf keine Hinweise darauf gefunden: open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf
Andreas Magnusson
41

Achten Sie auf die Rennbedingungen: Wenn die Datei zwischen der Prüfung "vorhanden" und dem Zeitpunkt des Öffnens verschwindet, schlägt Ihr Programm unerwartet fehl.

Es ist besser, die Datei zu öffnen, auf Fehler zu prüfen und wenn alles in Ordnung ist, etwas mit der Datei zu tun. Bei sicherheitskritischem Code ist dies sogar noch wichtiger.

Details zu Sicherheit und Rennbedingungen: http://www.ibm.com/developerworks/library/l-sprace.html

rlerallut
quelle
30

Ich bin ein glücklicher Boost-Benutzer und würde auf jeden Fall die Lösung von Andreas verwenden. Wenn Sie jedoch keinen Zugriff auf die Boost-Bibliotheken hatten, können Sie die Stream-Bibliothek verwenden:

ifstream file(argv[1]);
if (!file)
{
    // Can't open file
}

Es ist nicht ganz so schön wie boost :: filesystem :: existiert, da die Datei tatsächlich geöffnet wird ... aber dann ist das normalerweise das nächste, was Sie sowieso tun möchten.

MattyT
quelle
15
Mit diesem Code würden Sie jedoch auch in die if-Klausel springen, wenn Sie keine Berechtigungen für die Datei haben, obwohl diese vorhanden ist. In den meisten Fällen spielt es keine Rolle, ist aber dennoch erwähnenswert.
Scigor
1
Es wurde festgestellt, dass good () auch true ergibt, wenn das angegebene Argument ein Verzeichnis bezeichnet. Siehe stackoverflow.com/questions/9591036/…
FelixJongleur42
12

Verwenden Sie stat (), wenn es für Ihre Anforderungen plattformübergreifend genug ist. Es ist jedoch kein C ++ - Standard, sondern POSIX.

Unter MS Windows gibt es _stat, _stat64, _stati64, _wstat, _wstat64, _wstati64.

activout.se
quelle
1
<sys / types.h> und <sys / stat.h> Siehe msdn.microsoft.com/en-us/library/14h5k7ff(VS.71).aspx
activout.se
1
Schöne Antwort +1 für NOT USING BOOST , da es ein Overkill ist, aber es war nicht trivial, das von dem zu schreiben, was hier bereitgestellt wird, also habe ich gerade eine Antwort gepostet. Überprüfe es bitte.
Gsamaras
9

Wie wäre es mit access?

#include <io.h>

if (_access(filename, 0) == -1)
{
    // File does not exist
}
rauben
quelle
Ist io.h normalerweise unter Windows und Linux verfügbar, auch wenn es nicht Standard ist?
c0m4
1
access () ist eine POSIX-Funktion, die unter Linux über <unistd.h> verfügbar ist.
Alex B
9

Eine andere Möglichkeit besteht darin, die good()Funktion im Stream zu verwenden:

#include <fstream>     
bool checkExistence(const char* filename)
{
     ifstream Infield(filename);
     return Infield.good();
}
Samer
quelle
7

Ich würde es mir noch einmal überlegen, ob eine Datei existiert. Stattdessen sollten Sie versuchen, es (in Standard C oder C ++) in demselben Modus zu öffnen, in dem Sie es verwenden möchten. Was nützt es zu wissen, dass die Datei existiert, wenn sie beispielsweise nicht beschreibbar ist, wenn Sie sie verwenden müssen?

Sprudler
quelle
Was ist, wenn Sie ein lsähnliches Programm schreiben ? Ich vermute, das Originalposter hier möchte die Datei überhaupt nicht öffnen. Die stat-Funktion von Posix soll Ihnen jedoch Informationen über die Berechtigungen der Datei geben, damit das Problem behoben wird.
Michael
6

Wenn Ihr Compiler C ++ 17 unterstützt, benötigen Sie keinen Boost. Sie können ihn einfach verwenden std::filesystem::exists

#include <iostream> // only for std::cout
#include <filesystem>

if (!std::filesystem::exists("myfile.txt"))
{
    std::cout << "File not found!" << std::endl;
}
AlbertM
quelle
3

NEIN ERFORDERLICH , was ein Overkill wäre .


Verwenden Sie stat () (jedoch nicht plattformübergreifend, wie von pavon erwähnt) wie folgt:

#include <sys/stat.h>
#include <iostream>

// true if file exists
bool fileExists(const std::string& file) {
    struct stat buf;
    return (stat(file.c_str(), &buf) == 0);
}

int main() {
    if(!fileExists("test.txt")) {
        std::cerr << "test.txt doesn't exist, exiting...\n";
        return -1;
    }
    return 0;
}

Ausgabe:

C02QT2UBFVH6-lm:~ gsamaras$ ls test.txt
ls: test.txt: No such file or directory
C02QT2UBFVH6-lm:~ gsamaras$ g++ -Wall main.cpp
C02QT2UBFVH6-lm:~ gsamaras$ ./a.out
test.txt doesn't exist, exiting...

Eine andere Version (und das) finden Sie hier .

gsamaras
quelle
Nicht der Downvoter, sondern die Frage nach einer plattformübergreifenden Lösung, und stat ist nicht auf allen Plattformen vorhanden.
Pavon
0

Wenn Sie bereits die Eingabedateistreamklasse ( ifstream) verwenden, können Sie deren Funktion verwenden fail().

Beispiel:

ifstream myFile;

myFile.open("file.txt");

// Check for errors
if (myFile.fail()) {
    cerr << "Error: File could not be found";
    exit(1);
}
Reza Saadati
quelle