【问题标题】:c - fopen opening directories?c - fopen 打开目录?
【发布时间】:2017-03-18 15:28:50
【问题描述】:

我正在使用fopen() 来确定我是在打开文件还是这样的目录:

FILE *f;

f = fopen(path, "r");

if (f != NULL){

// found file

}

else {

// found a directory

}

并且 path 当前是指向目录的路径,而不是文件,它看起来像这样:

/home/me/Desktop/newfolder

但是,当我运行代码时,它说它找到了一个文件,即使它指向一个文件夹,因此它应该返回 NULL 指针,还是不返回?

我正在开发 Ubuntu。

【问题讨论】:

标签: c linux fopen


【解决方案1】:

C 标准没有提及任何关于fopening 目录的内容。

但是http://pubs.opengroup.org/onlinepubs/9699919799/functions/fopen.html 说以下(强调我的):

如果出现以下情况,fopen() 函数将失败:
[…]
[EISDIR] 命名文件是一个目录,模式需要写权限。

因此,如果您将 fopen(path, "r") 更改为例如fopen(path, "r+") 那么如果 path 引用一个目录,它应该会失败:

bool isDirectory(const char* path) {
    FILE *f = fopen(path, "r+");
    if (f) {
        fclose(f);
        return false;
    }
    return errno == EISDIR;
}

【讨论】:

  • @JHH 确实如此,r+ 不是更好吗?
  • 这行得通...但这是一个糟糕的解决方案,因为它会导致您的程序无法打开您只有读取权限的任何文件。
【解决方案2】:

先试试这个:

#include <dirent.h>

DIR* dir = opendir(path);
if (dir)
{
    /* Directory exists. Do stuff. */
    closedir(dir);
}
if(errno == ENOTDIR)
{   
    /* Exists but is not a directory */
}

【讨论】:

  • 问题是,我不仅要判断目录是否存在,还要判断输入是否为文件。
  • 所以在你知道它不是一个目录之后检查它是否是一个文件:) 但这不应该是必要的。我相信errno == ENOTDIR 暗示了一些东西在那里但不是一个目录,这意味着一个文件。
  • 如果是符号链接呢?
【解决方案3】:

先显示代码

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int is_reg_file(const char *path)
{
    struct stat statbuf;
    stat(path, &statbuf);
    // test for a regular file
    if (S_ISREG(statbuf.st_mode))
        return 1;
    return 0;
}

int is_dir(const char *path)
{
    struct stat statbuf;
    stat(path, &statbuf);
    if (S_ISDIR(statbuf.st_mode))
        return 1;
    return 0;
}

stat结构体定义如下,详细内容可参见stat(2)手册。

struct stat {
    dev_t     st_dev;         /* ID of device containing file */
    ino_t     st_ino;         /* Inode number */
    mode_t    st_mode;        /* File type and mode */
    nlink_t   st_nlink;       /* Number of hard links */
    uid_t     st_uid;         /* User ID of owner */
    gid_t     st_gid;         /* Group ID of owner */
    dev_t     st_rdev;        /* Device ID (if special file) */
    off_t     st_size;        /* Total size, in bytes */
    blksize_t st_blksize;     /* Block size for filesystem I/O */
    blkcnt_t  st_blocks;      /* Number of 512B blocks allocated */
    ...
};

st_mode 中定义的文件类型和一些宏可以在inode(7) 手册中找到。

  POSIX  refers  to the stat.st_mode bits corresponding to the mask S_IFMT (see below)
       as the file type, the 12 bits corresponding to the mask 07777 as the file mode  bits
       and the least significant 9 bits (0777) as the file permission bits.

       The following mask values are defined for the file type:

           S_IFMT     0170000   bit mask for the file type bit field

           S_IFSOCK   0140000   socket
           S_IFLNK    0120000   symbolic link
           S_IFREG    0100000   regular file
           S_IFBLK    0060000   block device
           S_IFDIR    0040000   directory
           S_IFCHR    0020000   character device
           S_IFIFO    0010000   FIFO

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-14
    • 2018-08-23
    • 1970-01-01
    • 1970-01-01
    • 2015-07-28
    • 2019-09-30
    • 2011-04-03
    • 1970-01-01
    相关资源
    最近更新 更多