Какой лучший способ проверить, существует ли файл в C?

Есть ли лучший способ, чем просто открыть файл?

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

Ответ 1

Найдите функцию access(), найденную в unistd.h. Вы можете заменить свою функцию на

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

Вы также можете использовать R_OK, W_OK и X_OK вместо F_OK, чтобы проверить разрешение на чтение, разрешение на запись и разрешение на выполнение (соответственно), а не существование, и вы можете ИЛИ любой из их вместе (т.е. проверить как разрешение на чтение, так и запись с помощью R_OK|W_OK)

Обновление. Обратите внимание: в Windows вы не можете использовать W_OK для надежного тестирования для разрешения на запись, поскольку функция доступа не учитывает DACL. access( fname, W_OK ) может возвращать 0 (успех), потому что у файла нет атрибута только для чтения, но у вас все еще может не быть права на запись в файл.

Ответ 2

Используйте stat следующим образом:

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

и назови это так:

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

Ответ 3

Обычно, когда вы хотите проверить, существует ли файл, это потому, что вы хотите создать этот файл, если это не так. Ответ Graeme Perrow хорош, если вы не хотите создать этот файл, но если вы это сделаете, он будет уязвим для условий гонки: другой процесс может создать файл между вами, проверяя, существует ли он, и вы фактически открывая его, чтобы написать ему. (Не смейтесь... это может иметь последствия плохой безопасности, если созданный файл был символической ссылкой!)

Если вы хотите проверить наличие и создать файл, если он не существует, atomically, чтобы не было условий гонки, используйте это:

#include <fcntl.h>
#include <errno.h>

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 */
}

Ответ 4

Да. Используйте stat(). См. справочную страницу дляstat(2).

stat() потерпит неудачу, если файл не существует, в противном случае, скорее всего, это удастся. Если он существует, но у вас нет доступа на чтение к каталогу, в котором он существует, он также потерпит неудачу, но в этом случае произойдет сбой любого метода (как вы можете проверить содержимое каталога, который вы можете не видеть в соответствии с правами доступа? Просто нельзя).

О, как уже упоминалось, вы также можете использовать access(). Однако я предпочитаю stat(), так как, если файл существует, он сразу же даст мне много полезной информации (когда он последний раз обновлялся, насколько он велик, владелец и/или группа, которой принадлежит файл, права доступа и т.д.) ,

Ответ 5

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
        }

Ответ 6

Из визуальной справки C++ я склоняюсь к

/* ACCESS.C: This example uses _access to check the
 * file named "ACCESS.C" to see if it exists and if
 * writing is allowed.
 */

#include  <io.h>
#include  <stdio.h>
#include  <stdlib.h>

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

Также стоит отметить значения режима _access(const char *path,int mode):

  • 00: только существование

  • 02: разрешение на запись

  • 04: разрешение на чтение

  • 06: разрешение на чтение и запись

Так как ваш fopen мог выйти из строя в ситуациях, когда файл существовал, но не мог быть открыт по запросу.

Изменение: Просто прочитайте сообщение Меки. stat() выглядит более аккуратно. Хо гул.

Ответ 7

Вы можете использовать функцию realpath().

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

Ответ 8

Я думаю, что функция access(), которая находится в unistd.h, является хорошим выбором для Linux (вы можете использовать stat).

Вы можете использовать его так:

#include <stdio.h>
#include <stdlib.h>
#include<unistd.h>

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

И вы получите следующий вывод:

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

Ответ 9

Для Windows проверьте следующую функцию: HANDLE FindFirstFile (...);