¿Cuál es la mejor forma de comprobar si existe un archivo en C ++? (plataforma cruzada)

Respuestas:

170

Utilice boost :: sistema de archivos :

#include <boost/filesystem.hpp>

if ( !boost::filesystem::exists( "myfile.txt" ) )
{
  std::cout << "Can't find my file!" << std::endl;
}
Andreas Magnusson
fuente
68
Parece ser un poco complicado instalar una enorme biblioteca de terceros para hacer algo que debería ser simple
c0m4
89
Boost es una biblioteca donde se desarrolla gran parte de lo que eventualmente será parte de la biblioteca estándar de C ++. Muchas de las personas involucradas con boost son personas involucradas con el estándar C ++. Así que boost no es solo una biblioteca de terceros. Si está programando en C ++, ¡ debería tener instalado boost!
Andreas Magnusson
Me parece recordar que b :: fs :: existe devuelve "true" en archivos no existentes en recursos compartidos de red: "\\ machine \ share \ this_file_doesnt_exist" => true. La última vez que verifiqué fue en boost 1.33,
tenga
Si su compilador viene con una implementación tr1, ni siquiera necesita instalar Boost. Estará en el sistema de archivos std :: tr1 ::
Nemanja Trifunovic
1
En realidad, ASFAIK no hizo TR1 pero se agregará en una etapa posterior. Tampoco encontré ninguna referencia a él en el borrador oficial de TR1: open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf
Andreas Magnusson
41

Tenga cuidado con las condiciones de carrera: si el archivo desaparece entre la comprobación de "existe" y el momento en que lo abre, su programa fallará inesperadamente.

Es mejor ir y abrir el archivo, verificar si hay fallas y si todo está bien, haga algo con el archivo. Es aún más importante con el código crítico para la seguridad.

Detalles sobre seguridad y condiciones de carrera: http://www.ibm.com/developerworks/library/l-sprace.html

rlerallut
fuente
30

Soy un usuario de boost feliz y sin duda usaría la solución de Andreas. Pero si no tuvo acceso a las bibliotecas de impulso, puede usar la biblioteca de transmisión:

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

No es tan agradable como boost :: filesystem :: existe, ya que el archivo se abrirá realmente ... pero eso es lo siguiente que suele querer hacer de todos modos.

MattyT
fuente
15
Pero con este código también saltaría a la cláusula if si no tiene permisos para el archivo, aunque existe. En la mayoría de los casos no importará, pero vale la pena mencionarlo.
scigor
1
Noté que good () también da como resultado verdadero si el argumento dado denota un directorio, consulte stackoverflow.com/questions/9591036/…
FelixJongleur42
12

Utilice stat (), si es lo suficientemente multiplataforma para sus necesidades. Sin embargo, no es el estándar C ++, sino POSIX.

En MS Windows hay _stat, _stat64, _stati64, _wstat, _wstat64, _wstati64.

activout.se
fuente
1
<sys / types.h> y <sys / stat.h> Consulte msdn.microsoft.com/en-us/library/14h5k7ff(VS.71).aspx
activout.se
1
Buena respuesta +1 para NO USAR BOOST , ya que es una exageración, sin embargo, no fue trivial escribir eso de lo que se proporciona aquí, así que publiqué una respuesta. Verifícalo por favor.
gsamaras
9

¿Qué tal access?

#include <io.h>

if (_access(filename, 0) == -1)
{
    // File does not exist
}
Robar
fuente
¿Está io.h normalmente disponible en Windows y Linux incluso si no es estándar?
C0m4
1
access () es la función POSIX que está disponible a través de <unistd.h> en Linux.
Alex B
9

Otra posibilidad consiste en utilizar la good()función en el stream:

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

Reconsideraría intentar averiguar si existe un archivo. En su lugar, debe intentar abrirlo (en Standard C o C ++) en el mismo modo en el que desea usarlo. ¿De qué sirve saber que el archivo existe si, por ejemplo, no se puede escribir cuando es necesario utilizarlo?

fizzer
fuente
¿Qué pasa si estás escribiendo un lsprograma similar? Supongo que el póster original aquí no quiere abrir el archivo, en absoluto. Sin embargo, se supone que la función de estadísticas de Posix le brinda información sobre los permisos del archivo, por lo que solucionaría ese problema.
Michael
6

Si su compilador es compatible con C ++ 17, no necesita boost, simplemente puede usar 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
fuente
3

NO REQUERIDO , lo cual sería una exageración .


Use stat () (no multiplataforma, como lo menciona pavon), así:

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

Salida:

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

Otra versión (y esa) se puede encontrar aquí .

gsamaras
fuente
No el votante negativo, pero la pregunta pedía una solución multiplataforma, y ​​la estadística no existe en todas las plataformas.
Pabellón
0

Si ya está usando la clase de flujo de archivos de entrada ( ifstream), puede usar su función fail().

Ejemplo:

ifstream myFile;

myFile.open("file.txt");

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