简体   繁体   English

检查文件是否存在于 C 中的最佳方法是什么?

[英]What's the best way to check if a file exists in C?

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

Look up the access() function, found in unistd.h .查找在unistd.h中找到的access()函数。 You can replace your function with您可以将您的功能替换为

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

Under Windows (VC) unistd.h does not exist.在 Windows (VC) 下, unistd.h不存在。 To make it work it is necessary to define:为了使其工作,有必要定义:

#ifdef WIN32
#include <io.h>
#define F_OK 0
#define access _access
#endif

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 (ie check for both read and write permission using R_OK|W_OK )您还可以使用R_OKW_OKX_OK代替F_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.更新:请注意,在 Windows 上,您不能使用W_OK来可靠地测试写权限,因为访问功能不考虑 DACL。 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. access( fname, W_OK )可能返回 0(成功),因为文件没有设置只读属性,但您仍然可能没有写入文件的权限。

Use stat like this:像这样使用stat

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

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

and call it like this:并这样称呼它:

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

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.如果您不想创建该文件, Graeme Perrow 的回答很好,但如果您这样做,它很容易受到竞争条件的影响:另一个进程可以在您检查文件是否存在之间创建文件,然后您实际上打开它以写入它. (Don't laugh... this could have bad security implications if the file created was a symlink!) (不要笑......如果创建的文件是符号链接,这可能会产生不良的安全隐患!)

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

Yes.是的。 Use stat() .使用stat() See the man page for stat(2) .请参阅stat(2)的手册页。

stat() will fail if the file doesn't exist, otherwise most likely succeed.如果文件不存在, stat()将失败,否则很可能会成功。 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).如果它确实存在,但你对它所在的目录没有读权限,它也会失败,但在这种情况下任何方法都会失败(你怎么能检查一个你可能根据访问权限看不到的目录的内容?很简单,你不能)。

Oh, as someone else mentioned, you can also use access() .哦,正如其他人提到的,您也可以使用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).但是我更喜欢stat() ,就好像文件存在一样,它会立即为我提供很多有用的信息(上次更新时间、文件大小、拥有文件的所有者和/或组、访问权限等) .

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
        }

You can use realpath() function.您可以使用 realpath() 函数。

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

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 _access(const char *path, int mode ) :同样值得注意的是_access(const char *path, int mode )的模式值:

  • 00: Existence only 00:仅存在

  • 02: Write permission 02:写权限

  • 04: Read permission 04:读取权限

  • 06: Read and write permission 06:读写权限

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.编辑:只需阅读 Mecki 的帖子。 stat() does look like a neater way to go. stat()看起来确实是一种更简洁的方法。 Ho hum.呵呵。

I think that access() function, which is found in unistd.h is a good choice for Linux (you can use stat too).我认为unistd.h中的access()函数是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

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

对于Windows,请查看以下函数:HANDLE FindFirstFile(...);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM