Qual è il modo migliore per verificare se un file esiste in C ++? (multipiattaforma)


97

Ho letto le risposte per Qual è il modo migliore per verificare se un file esiste in C? (multipiattaforma) , ma mi chiedo se esiste un modo migliore per farlo utilizzando le librerie c ++ standard? Preferibilmente senza tentare di aprire il file.

Entrambi state accesssono praticamente ingoogabili. Cosa dovrei #includeusare questi?


<io.h> per l'accesso (che potrebbe effettivamente essere _access).
Rob il

Sì, come da lì sottolineato.
c0m4

Risposte:


170

Usa boost :: filesystem :

#include <boost/filesystem.hpp>

if ( !boost::filesystem::exists( "myfile.txt" ) )
{
  std::cout << "Can't find my file!" << std::endl;
}

68
Sembra essere un po 'complicato installare un'enorme libreria di terze parti per fare qualcosa che dovrebbe essere semplice
c0m4

89
Boost è una libreria in cui viene sviluppata gran parte di ciò che alla fine farà parte della libreria standard C ++. Molte delle persone coinvolte in boost sono persone coinvolte nello standard C ++. Quindi boost non è solo una libreria di terze parti. Se stai programmando in C ++ dovresti avere Boost installato!
Andreas Magnusson

Mi sembra di ricordare che b :: fs :: exist restituisce "true" su file inesistenti su condivisioni di rete: "\\ machine \ share \ this_file_doesnt_exist" => true. L'ultima volta che ho controllato era in boost 1.33,
fai

Se il tuo compilatore viene fornito con un'implementazione tr1, non è nemmeno necessario installare Boost. Sarà nello std :: tr1 :: filesystem
Nemanja Trifunovic

1
In realtà ASFAIK non ha prodotto TR1 ma verrà aggiunto in una fase successiva. Inoltre non ho trovato alcun riferimento ad esso nella bozza ufficiale di TR1: open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf
Andreas Magnusson

41

Fai attenzione alle condizioni di gara: se il file scompare tra il controllo "esiste" e l'ora in cui lo apri, il tuo programma fallirà inaspettatamente.

È meglio andare ad aprire il file, controllare se non è riuscito e se tutto va bene allora fare qualcosa con il file. È ancora più importante con il codice critico per la sicurezza.

Dettagli sulla sicurezza e sulle condizioni di gara: http://www.ibm.com/developerworks/library/l-sprace.html


30

Sono un felice utente boost e utilizzerei sicuramente la soluzione di Andreas. Ma se non hai accesso alle librerie boost puoi usare la libreria stream:

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

Non è così bello come boost :: filesystem :: esiste poiché il file verrà effettivamente aperto ... ma di solito è la prossima cosa che vuoi fare comunque.


15
Ma con questo codice salteresti anche nella clausola if se non hai i permessi per il file, sebbene esista. Nella maggior parte dei casi non importa, ma vale comunque la pena menzionarlo.
scigor

1
Ha notato che buona () produce anche vero se l'argomento dato denota una directory, vedere stackoverflow.com/questions/9591036/...
FelixJongleur42

12

Usa stat (), se è abbastanza multipiattaforma per le tue esigenze. Tuttavia, non è lo standard C ++, ma POSIX.

Su MS Windows ci sono _stat, _stat64, _stati64, _wstat, _wstat64, _wstati64.


1

1
Bella risposta +1 per NON USARE BOOST , poiché è eccessivo, tuttavia non è stato banale scriverlo da ciò che viene fornito qui, quindi ho appena pubblicato una risposta. Controllalo per favore.
gsamaras

9

Che ne dici access?

#include <io.h>

if (_access(filename, 0) == -1)
{
    // File does not exist
}

Io.h è normalmente disponibile su Windows e Linux anche se non è standard?
c0m4

1
access () è la funzione POSIX disponibile tramite <unistd.h> su Linux.
Alex B

9

Un'altra possibilità consiste nell'utilizzare la good()funzione nel flusso:

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

7

Riconsidererei di provare a scoprire se esiste un file. Invece, dovresti provare ad aprirlo (in Standard C o C ++) nella stessa modalità in cui intendi usarlo. A che serve sapere che il file esiste se, ad esempio, non è scrivibile quando è necessario utilizzarlo?


E se stai scrivendo un lsprogramma simile? Immagino che il poster originale qui non voglia aprire il file, affatto. Tuttavia, la funzione stat di Posix dovrebbe darti informazioni sui permessi del file, quindi risolverebbe il problema.
Michael

6

Se il tuo compilatore supporta C ++ 17 non hai bisogno di boost, puoi semplicemente usare std::filesystem::exists

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

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

3

NO OBBLIGATORIO , che sarebbe eccessivo .


Usa stat () (non multipiattaforma anche se come menzionato da pavon), in questo modo:

#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;
}

Produzione:

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...

Un'altra versione (e quella) può essere trovata qui .


Non il downvoter, ma la domanda richiedeva una soluzione multipiattaforma e la statistica non esiste su tutte le piattaforme.
padiglione

0

Se stai già usando il file di input stream class ( ifstream), puoi usare la sua funzione fail().

Esempio:

ifstream myFile;

myFile.open("file.txt");

// Check for errors
if (myFile.fail()) {
    cerr << "Error: File could not be found";
    exit(1);
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.