检查一个文件在C中是否存在的最好方法是什么?

有比简单地打开文件更好的方法吗?

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

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

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

哦,正如其他人提到的,您也可以使用access()。然而,我更喜欢stat(),因为如果文件存在,它会立即给我很多有用的信息(它最后一次更新是什么时候,它有多大,所有者和/或拥有文件的组,访问权限,等等)。

查找access()函数,在unistd.h中找到。你可以用

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

在Windows (VC)下unistd.h不存在。为了使它起作用,有必要定义:

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

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

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

像这样使用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;
}

从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()看起来确实是一个更整洁的方式。何鸿燊的嗡嗡声。

通常当您想要检查一个文件是否存在时,这是因为如果它不存在,您想要创建该文件。如果您想要创建文件,格雷姆·佩罗的回答很好,但是如果您这样做,它很容易受到竞态条件的影响:在您检查它是否存在和您实际打开它并写入它之间,另一个进程可能会创建文件。(别笑…如果创建的文件是符号链接,这可能会有安全隐患!)

如果你想检查是否存在而且,创建文件,如果它不存在,自动,这样就没有竞争条件,然后使用这个:

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

我认为在unistd.h中找到的访问()函数对于Linux是一个很好的选择(你也可以使用统计)。

你可以这样使用它:

#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

您可以使用realpath()函数。

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