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


97

He leído las respuestas de ¿Cuál es la mejor manera de comprobar si existe un archivo en C? (multiplataforma) , pero me pregunto si hay una mejor manera de hacer esto usando libs estándar de C ++. Preferiblemente sin intentar abrir el archivo en absoluto.

Ambos staty accessson prácticamente ingooglebles. ¿Qué debo #includeusar estos?


<io.h> para acceder (que en realidad podría ser _access).
Rob

Sí, como se señaló desde allí.
C0m4

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

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


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.


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.


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
}

¿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();
}

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?


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

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


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);
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.