检查文件是否存在于C中最好的方法是什么?(跨平台)

时间:2022-07-25 12:16:32

Is there a better way than simply trying to open the file?

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

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

8 个解决方案

#1


438  

Look up the access() function, found in unistd.h. You can replace your function with

查找在unistd.h中找到的access()函数。你可以用它代替你的功能。

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

You can also use R_OK, W_OK, and X_OK in place of F_OK to check for read permission, write permission, and execute permission (respectively) rather than existence, and you can OR any of them together (i.e. check for both read and write permission using R_OK|W_OK)

您还可以使用R_OK、W_OK和X_OK来检查读权限、写权限和执行权限(分别),而不是存在,您可以或任何一起(即使用R_OK|W_OK检查读和写权限)

Update: Note that on Windows, you can't use W_OK to reliably test for write permission, since the access function does not take DACLs into account. access( fname, W_OK ) may return 0 (success) because the file does not have the read-only attribute set, but you still may not have permission to write to the file.

更新:请注意,在Windows上,您不能使用W_OK来可靠地测试写权限,因为访问函数没有考虑到dacl。访问(fname, W_OK)可能返回0(成功),因为文件没有只读属性集,但是您仍然可能没有权限写入文件。

#2


87  

Use stat like this:

使用统计如下:

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

and call it like this:

这样称呼它:

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

#3


63  

Usually when you want to check if a file exists, it's because you want to create that file if it doesn't. Graeme Perrow's answer is good if you don't want to create that file, but it's vulnerable to a race condition if you do: another process could create the file in between you checking if it exists, and you actually opening it to write to it. (Don't laugh... this could have bad security implications if the file created was a symlink!)

通常,当您想要检查某个文件是否存在时,它是因为您想要创建该文件,如果它不存在。Graeme Perrow的回答很好,如果你不想创建那个文件,但是如果你这样做的话,它很容易受到一个竞争条件的影响:另一个进程可以在你检查它是否存在的时候创建这个文件,并且你实际打开它来给它写信。(别笑…如果创建的文件是一个符号链接,这可能会带来不好的安全影响!

If you want to check for existence and create the file if it doesn't exist, atomically so that there are no race conditions, then use this:

如果您想要检查存在并创建文件,如果它不存在,那么就不存在任何竞争条件,然后使用这个:

#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


27  

Yes. Use stat(). See link.

是的。使用stat()。看到链接。

Stat will fail if the file doesn't exist, otherwise most likely succeed. If it does exist, but you have no read access to the directory where it exists, it will also fail, but in that case any method will fail (how can you inspect the content of a directory you may not see according to access rights? Simply, you can't).

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

Oh, as someone else mentioned, you can also use access(). However I prefer stat(), as if the file exists it will immediately get me lots of useful information (when was it last updated, how big is it, owner and/or group that owns the file, access permissions, and so on).

哦,正如别人提到的,你也可以使用access()。但是,我更喜欢stat(),就像文件存在一样,它会立即给我带来很多有用的信息(当它最后一次更新时,它的大小、所有者和/或拥有文件、访问权限等的组)。

#5


5  

From the Visual C++ help, I'd tend to go with

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

Also worth noting mode values of _accesss(const char *path,int mode)

也值得注意_accesss的模式值(const char *path,int模式)

00 Existence only

00只存在

02 Write permission

02年写权限

04 Read permission

04读权限

06 Read and write permission

读和写权限。

As your fopen could fail in situations where the file existed but could not be opened as requested.

因为您的fopen可能在文件存在的情况下失败,但是不能按请求打开。

Edit: Just read Mecki's post. stat() does look like a neater way to go. Ho hum.

编辑:读Mecki的帖子。stat()看起来是一种更整洁的方法。何鸿燊的嗡嗡声。

#6


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
        }

#7


2  

I think that access() function, which is found in unistd.h is a good choice for Linux (you can use stat too).

我认为access()函数是在unistd中找到的。h是Linux的一个不错的选择(您也可以使用stat)。

You can Use it like this:

你可以这样使用:

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

And you get the following Output:

得到如下输出:

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

#8


0  

You can use realpath() function.

您可以使用realpath()函数。

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

#1


438  

Look up the access() function, found in unistd.h. You can replace your function with

查找在unistd.h中找到的access()函数。你可以用它代替你的功能。

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

You can also use R_OK, W_OK, and X_OK in place of F_OK to check for read permission, write permission, and execute permission (respectively) rather than existence, and you can OR any of them together (i.e. check for both read and write permission using R_OK|W_OK)

您还可以使用R_OK、W_OK和X_OK来检查读权限、写权限和执行权限(分别),而不是存在,您可以或任何一起(即使用R_OK|W_OK检查读和写权限)

Update: Note that on Windows, you can't use W_OK to reliably test for write permission, since the access function does not take DACLs into account. access( fname, W_OK ) may return 0 (success) because the file does not have the read-only attribute set, but you still may not have permission to write to the file.

更新:请注意,在Windows上,您不能使用W_OK来可靠地测试写权限,因为访问函数没有考虑到dacl。访问(fname, W_OK)可能返回0(成功),因为文件没有只读属性集,但是您仍然可能没有权限写入文件。

#2


87  

Use stat like this:

使用统计如下:

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

and call it like this:

这样称呼它:

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

#3


63  

Usually when you want to check if a file exists, it's because you want to create that file if it doesn't. Graeme Perrow's answer is good if you don't want to create that file, but it's vulnerable to a race condition if you do: another process could create the file in between you checking if it exists, and you actually opening it to write to it. (Don't laugh... this could have bad security implications if the file created was a symlink!)

通常,当您想要检查某个文件是否存在时,它是因为您想要创建该文件,如果它不存在。Graeme Perrow的回答很好,如果你不想创建那个文件,但是如果你这样做的话,它很容易受到一个竞争条件的影响:另一个进程可以在你检查它是否存在的时候创建这个文件,并且你实际打开它来给它写信。(别笑…如果创建的文件是一个符号链接,这可能会带来不好的安全影响!

If you want to check for existence and create the file if it doesn't exist, atomically so that there are no race conditions, then use this:

如果您想要检查存在并创建文件,如果它不存在,那么就不存在任何竞争条件,然后使用这个:

#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


27  

Yes. Use stat(). See link.

是的。使用stat()。看到链接。

Stat will fail if the file doesn't exist, otherwise most likely succeed. If it does exist, but you have no read access to the directory where it exists, it will also fail, but in that case any method will fail (how can you inspect the content of a directory you may not see according to access rights? Simply, you can't).

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

Oh, as someone else mentioned, you can also use access(). However I prefer stat(), as if the file exists it will immediately get me lots of useful information (when was it last updated, how big is it, owner and/or group that owns the file, access permissions, and so on).

哦,正如别人提到的,你也可以使用access()。但是,我更喜欢stat(),就像文件存在一样,它会立即给我带来很多有用的信息(当它最后一次更新时,它的大小、所有者和/或拥有文件、访问权限等的组)。

#5


5  

From the Visual C++ help, I'd tend to go with

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

Also worth noting mode values of _accesss(const char *path,int mode)

也值得注意_accesss的模式值(const char *path,int模式)

00 Existence only

00只存在

02 Write permission

02年写权限

04 Read permission

04读权限

06 Read and write permission

读和写权限。

As your fopen could fail in situations where the file existed but could not be opened as requested.

因为您的fopen可能在文件存在的情况下失败,但是不能按请求打开。

Edit: Just read Mecki's post. stat() does look like a neater way to go. Ho hum.

编辑:读Mecki的帖子。stat()看起来是一种更整洁的方法。何鸿燊的嗡嗡声。

#6


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
        }

#7


2  

I think that access() function, which is found in unistd.h is a good choice for Linux (you can use stat too).

我认为access()函数是在unistd中找到的。h是Linux的一个不错的选择(您也可以使用stat)。

You can Use it like this:

你可以这样使用:

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

And you get the following Output:

得到如下输出:

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

#8


0  

You can use realpath() function.

您可以使用realpath()函数。

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