¿Cuál es la mejor manera de verificar si un archivo existe en C? (plataforma cruzada)

¿Hay una mejor manera que simplemente tratar de abrir el archivo?

int exists(const char *fname) { FILE *file; if ((file = fopen(fname, "r"))) { fclose(file); return 1; } return 0; } 

Busque la función access() , que se encuentra en unistd.h . Puedes reemplazar tu función con

 if( access( fname, F_OK ) != -1 ) { // file exists } else { // file doesn't exist } 

También puede usar R_OK , W_OK y X_OK en lugar de F_OK para verificar el permiso de lectura, permiso de escritura y permiso de ejecución (respectivamente) en lugar de existencia, y usted puede O cualquiera de ellos juntos (es decir, verificar el permiso de lectura y escritura usando R_OK|W_OK )

Actualización : tenga en cuenta que en Windows, no puede usar W_OK para comprobar de forma confiable el permiso de escritura, ya que la función de acceso no tiene en cuenta las DACL. access( fname, W_OK ) puede devolver 0 (éxito) porque el archivo no tiene el conjunto de atributos de solo lectura, pero aún puede no tener permiso para escribir en el archivo.

Usa estadísticas como esta:

 int file_exist (char *filename) { struct stat buffer; return (stat (filename, &buffer) == 0); } 

y llámalo así:

 if (file_exist ("myfile.txt")) { printf ("It exists\n"); } 

Por lo general, cuando desea verificar si existe un archivo, es porque desea crear ese archivo si no lo hace. La respuesta de Graeme Perrow es buena si no quieres crear ese archivo, pero es vulnerable a una condición de carrera si lo haces: otro proceso podría crear el archivo entre el momento en que compruebas si existe y lo estás abriendo para escribir en él. . (No te rías … esto podría tener malas implicaciones de seguridad si el archivo creado fuera un enlace simbólico).

Si desea verificar la existencia y crear el archivo si no existe, atómicamente para que no existan condiciones de carrera, utilice esto:

 #include  #include  fd = open(pathname, O_CREAT | O_WRONLY | O_EXCL, S_IRUSR | S_IWUSR); if (fd < 0) { /* failure */ if (errno == EEXIST) { /* the file already existed */ ... } } else { /* now you can use the file */ } 

Sí. Usa stat () Ver enlace .

Stat fallará si el archivo no existe, de lo contrario es muy probable que tenga éxito. Si existe, pero no tiene acceso de lectura al directorio donde existe, también fallará, pero en ese caso cualquier método fallará (¿cómo puede inspeccionar el contenido de un directorio que puede no ver según los derechos de acceso? Simplemente, no puedes).

Ah, como alguien más mencionó, también puedes usar access (). Sin embargo, prefiero stat (), como si el archivo existe, de inmediato obtendré mucha información útil (cuándo se actualizó por última vez, qué tamaño tiene, propietario y / o grupo propietario del archivo, permisos de acceso, etc.) .

Desde la ayuda de Visual C ++, tendería a ir con

 /* ACCESS.C: This example uses _access to check the * file named "ACCESS.C" to see if it exists and if * writing is allowed. */ #include  #include  #include  void main( void ) { /* Check for existence */ if( (_access( "ACCESS.C", 0 )) != -1 ) { printf( "File ACCESS.C exists\n" ); /* Check for write permission */ if( (_access( "ACCESS.C", 2 )) != -1 ) printf( "File ACCESS.C has write permission\n" ); } } 

También vale la pena señalar los valores de modo de _accesss (const char * path, int mode )

00 Sólo existencia

02 Permiso de escritura

04 permiso de lectura

06 Permiso de lectura y escritura

Como su fopen podría fallar en situaciones donde el archivo existía pero no se podía abrir según lo solicitado.

Editar: acaba de leer la publicación de Mecki. stat () parece una manera más ordenada de ir. Ho hum.

 FILE *file; if((file = fopen("sample.txt","r"))!=NULL) { // file exists fclose(file); } else { //File not found, no memory leak since 'file' == NULL //fclose(file) would cause an error } 

Creo que la función access () , que se encuentra en unistd.h es una buena opción para Linux (también puedes usar estadísticas ).

Puedes usarlo así:

 #include  #include  #include void fileCheck(const char *fileName); int main (void) { char *fileName = "/etc/sudoers"; fileCheck(fileName); return 0; } void fileCheck(const char *fileName){ if(!access(fileName, F_OK )){ printf("The File %s\t was Found\n",fileName); }else{ printf("The File %s\t not Found\n",fileName); } if(!access(fileName, R_OK )){ printf("The File %s\t can be read\n",fileName); }else{ printf("The File %s\t cannot be read\n",fileName); } if(!access( fileName, W_OK )){ printf("The File %s\t it can be Edited\n",fileName); }else{ printf("The File %s\t it cannot be Edited\n",fileName); } if(!access( fileName, X_OK )){ printf("The File %s\t is an Executable\n",fileName); }else{ printf("The File %s\t is not an Executable\n",fileName); } } 

Y obtienes el siguiente resultado:

 The File /etc/sudoers was Found The File /etc/sudoers cannot be read The File /etc/sudoers it cannot be Edited The File /etc/sudoers is not an Executable 

Puede usar la función realpath ().

 resolved_file = realpath(file_path, NULL); if (!resolved_keyfile) { /*File dosn't exists*/ perror(keyfile); return -1; }