515

有没有比简单地尝试打开文件更好的方法?

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

8 回答 8

707

查找access()函数,在unistd.h. 您可以将您的功能替换为

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

您还可以使用R_OK,W_OKX_OK代替F_OK来检查读取权限,写入权限和执行权限(分别)而不是存在,您可以将它们中的任何一个放在一起(即使用 来检查读取写入权限R_OK|W_OK

更新:请注意,在 Windows 上,您不能使用W_OK可靠地测试写入权限,因为访问功能不考虑 DACL。access( fname, W_OK )可能会返回 0(成功),因为该文件没有设置只读属性,但您仍然可能没有写入该文件的权限。

于 2008-10-23T14:59:32.250 回答
130

像这样使用stat

#include <sys/stat.h>   // stat
#include <stdbool.h>    // bool type

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

并这样称呼它:

#include <stdio.h>      // printf

int main(int ac, char **av) {
    if (ac != 2)
        return 1;

    if (file_exists(av[1]))
        printf("%s exists\n", av[1]);
    else
        printf("%s does not exist\n", av[1]);

    return 0;
}
于 2008-10-23T15:00:53.727 回答
96

通常,当您要检查文件是否存在时,是因为如果不存在则要创建该文件。 如果您不想创建该文件, Graeme Perrow 的答案很好,但如果您这样做,它很容易受到竞争条件的影响:另一个进程可能会在您检查它是否存在之间创建该文件,然后您实际上打开它来写入它. (别笑……如果创建的文件是符号链接,这可能会带来不好的安全隐患!)

如果要检查是否存在在文件不存在时以原子方式创建文件以便没有竞争条件,请使用以下命令:

#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 */
}
于 2008-10-23T17:14:05.050 回答
34

是的。使用stat(). 请参阅手册页stat(2)

stat()如果文件不存在将失败,否则很可能成功。如果它确实存在,但您对它所在的目录没有读取权限,它也会失败,但在这种情况下,任何方法都会失败(如何根据访问权限检查您可能看不到的目录的内容?简单地说,你不能)。

哦,正如其他人提到的,您也可以使用access(). 但是我更喜欢stat(),好像文件存在一样,它会立即为我提供很多有用的信息(上次更新时间、文件大小、拥有文件的所有者和/或组、访问权限等)。

于 2008-10-23T14:59:16.070 回答
19
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
        }
于 2015-04-08T09:08:01.523 回答
6

从 Visual 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因为在文件存在但无法按要求打开的情况下,您可能会失败。

编辑:只需阅读 Mecki 的帖子。 stat()看起来确实是一个更整洁的方法。哼哼。

于 2008-10-23T15:07:01.343 回答
6

我认为在中找到的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
于 2015-12-09T17:14:28.353 回答
6

您可以使用 realpath() 函数。

resolved_file = realpath(file_path, NULL);
if (!resolved_keyfile) {
   /*File dosn't exists*/
   perror(keyfile);
   return -1;
}
于 2016-04-08T06:14:20.627 回答