工作中涉及到文件系统,有时候需要判断文件和目录是否存在,下面是一些前人的经验分享。
判断文件存在
对于判断文件是否存在,每个人有不同的方法!我通常采用两种方法 : open 和 access ;
这个俩个方法有相似之处,且有不同之处;下面为大家详细说明他们的不同之处:
open 是打开,读写等操作文件的一个函数,access就是一个判断文件权限的函数。在Linux下,由于文件有不同的权限,当当前用户没有对此文件的读权限的时候,用来判断文件是否存在,显然不合适。而access却可以做到。
open 的第一个参数是文件路径,第二个参数是打开文件选项,常用的有O_RDONLY(读),O_WRONLY(写),O_RDWR(读写),O_CREAT(创建)。 第三个参数通常在创建文件的时候才使用,给文件设定权限使用。
access的第一个参数是文件路径,第二个参数是测试的模式。常用的有R_OK:测试读权限,W_OK:测试写权限,X_OK:测试执行权限,F_OK:测试文件是否存在;
access函数
access函数按照实际用户ID和实际组进行访问权限测试。函数原型为:
#include <unistd.h>
int access(const char *pathname, int mode);
mode取值:
F_OK 测试文件是否存在
R_OK 测试读权限
W_OK 测试写权限
X_OK 测试执行权限
正确判断一个文件是否存在是用access函数,实现如下所示:
#include <unistd.h>
int is_file_exist(const char *file_path)
{
if(file_path == NULL)
return -1;
if( access(file_path, F_OK) == 0 )
return 0;
return -1;
}
我做个例子,写一个小程序来看两者的区别。
测试测序:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc , char **argv)
{
char path[50];
memset(path,0,50);
sprintf(path,"%s","./test");
int fd;
printf("access function -------------------------/n");
if((fd = access (path,F_OK)) == 0)
printf("[access] file exist!/n");
else
printf("[access] file not exist!!/n");
if((fd = access (path,R_OK)) == 0)
printf("[access] read file ok!/n");
else
printf("[access] read file no!/n");
if((fd = access (path,W_OK)) == 0)
printf("[access] write file ok!/n");
else
printf("[access] write file no!/n");
if((fd = access (path,X_OK)) == 0)
printf("[access] execute file ok!/n");
else
printf("[access] execute file no!/n");
printf("open function -------------------------/n");
if((fd = open (path,O_RDONLY)) == -1)
printf("[open] open no!/n");
else
{
close(fd);
printf("[open] open ok!/n");
}
if((fd = open (path,O_WRONLY)) == -1)
printf("[open] write no!/n");
else
{
close(fd);
printf("[open] write ok!/n");
}
if((fd = open (path,O_RDWR)) == -1)
printf("[open] rdwr no!/n");
else
{
close(fd);
printf("[open] rdwr ok!/n");
}
}
首先我们创建一个普通文件 test , 修改文件权限为0744,修改文件属主为root. 我们在普通用户mpeg4下操作.
[mpeg4@mc2800 file1]$ sudo chown root:root test
[mpeg4@mc2800 file1]$ sudo chmod 0744 test
[mpeg4@mc2800 file1]$ ls -l
total 20
-rwxrwxrwx 1 mpeg4 mpeg4 7157 2009-09-17 09:37 file
-rwxrwxrwx 1 mpeg4 mpeg4 991 2009-09-17 09:44 file.c
-rwxrwxrwx 1 mpeg4 mpeg4 94 2009-09-17 08:56 makefile
-rwxrwxrwx 1 mpeg4 mpeg4 3808 2009-08-20 13:52 records
-rwxr--r-- 1 root root 0 2009-09-17 10:06 test
好了,我们运行我的程序看结果:
[mpeg4@mc2800 file1]$ ./file
access function -------------------------
[access] file exist!
[access] read file ok!
[access] write file no!
[access] execute file no!
open function -------------------------
[open] open ok!
[open] write no!
[open] rdwr no!
很明显在用户有读权限的情况下,使用那个函数用来判断文件是否存在都可以。
现在我们把文件的权限改为0740:
sudo chmod 0740 test
再看测试结果:
[mpeg4@mc2800 file1]$ ./file
access function -------------------------
[access] file exist!
[access] read file no!
[access] write file no!
[access] execute file no!
open function -------------------------
[open] open no!
[open] write no!
[open] rdwr no!
可以看到,文件权限改变了,就不能用open函数来判断文件是否存在了。
我相信很多人都喜欢用open函数来判断文件是否存在,当然大家也都知道关于权限的问题,所以会采用一些必要测措施来控制出错。但是我建议判断文件是否存在最好用access函数。当我们要读取文件内容的时候可以使用open来判断文件是否存在,就算是因为没有读权限或者文件真的不存在,都无法实现读的操作,我们的目的也就达到了。
stat系列函数
stat函数用来返回与文件有关的结构信息。stat系列函数有三种情况,分别对应文件名称、文件描述符和符号链接文件。stat结构描述了文件的属性,主要包括文件的类型、文件大小等等。详细stat结构如下所示:
struct stat {
mode_t st_mode; // file type & mode(permissions)
ino_t st_ino; // i-node number(serial number)
dev_t st_dev; // device number(filesystem)
dev_t st_rdev; // device number for specials files
nlink_t st_nlink; // number of links
uid_t st_uid; // user ID of owner
gid_t st_gid; // group ID of owner
off_t st_size; // size in bytes, for regular files
time_t st_atime; // time of last access
time_t st_mtime; // time of last modification
time_t st_ctime; // time of last file status change
long st_blksize; // best I/O block size
long st_blocks; // number of 512-byte blocks allocated
};
我们可以通过stat获取文件的类型和文件大小等信息。文件类型有:普通文件、目录文件、块特殊文件、字符特殊文件、FIFO、套接字和符号链接。要想通过stat系列函数来判断文件或者目录是否存在,当执行stat函数,如果文件存在时,还需进一步判断该文件是普通文件还是目录文件。
stat系列函数错误返回-1,错误码存在errno中,errno取值如下:
1、ENOENT 参数file_name 指定的文件不存在
2、ENOTDIR 路径中的目录存在但却非真正的目录
3、ELOOP 欲打开的文件有过多符号连接问题, 上限为16 符号连接
4、EFAULT 参数buf 为无效指针, 指向无法存在的内存空间
5、EACCESS 存取文件时被拒绝
6、ENOMEM 核心内存不足
7、ENAMETOOLONG 参数file_name 的路径名称太长
判断目录:oepndir函数
opendir函数用来打开文件目录,成功返回指针,出错返回NULL。
函数原型为:
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);
实现如下:
#include <sys/types.h>
#include <dirent.h>
int is_dir_exist(const char *dir_path)
{
DIR *dirptr = NULL;
if(dir_path== NULL)
return -1;
if( dirptr=opendir(dir_path) == 0 ){
return -1;
}
closedir(dirptr );
return 0;
}