检查路径上的对象是否是跨平台的文件或目录?

时间:2020-07-12 02:39:04

标签: c filesystems cross-platform

您可以使用stat()函数来检查对象是文件还是目录,例如this。我的问题是<sys/stat.h>不在Windows上,并且我不确定Windows等效或Windows函数是什么。这个问题是我该怎么做this,但特别是以跨平台的方式。

在避免有条件地编译代码的同时,如何跨平台检查路径中的对象是C中的文件还是目录?尽管有almost identical question,但由于没有答案,它无济于事,并且删除了作者,因此无法维护该问题。

据我所知fopen()是跨平台的,opendir()readdir()scandir()等也是跨平台的,所以为什么不简单地检查对象是否是文件或目录是跨平台的?如果没有办法,而有条件地编译代码是唯一的办法,我该如何在Windows中做到这一点?

1 个答案:

答案 0 :(得分:0)

不幸的是,在C语言中,没有简单,可移植或直接的方法来完成此操作。

不过,这是我为跨平台库编写的一些C ++代码从我转换的一些C代码,可用于检查文件或目录是否存在:

#include <sys/stat.h>
#include <sys/types.h>
#if defined(OS_WIN)
    #include <windows.h>
#else
    #include <dirent.h> // for *Nix directory access
    #include <unistd.h>
#endif

bool file_exists(const char* file)
{
    if (file == NULL) { return false; }
    #if defined(OS_WIN)
        #if defined(WIN_API)
            // if you want the WinAPI, versus CRT
            if (strnlen(file, MAX_PATH+1) > MAX_PATH) {
                // ... throw error here or ...
                return false;
            }
            DWORD res = GetFileAttributesA(file);
            return (res != INVALID_FILE_ATTRIBUTES &&
                !(res & FILE_ATTRIBUTE_DIRECTORY));
        #else
            // Use Win CRT
            struct stat fi;
            if (_stat(file, &fi) == 0) {
                #if defined(S_ISSOCK)
                    // sockets come back as a 'file' on some systems
                    // so make sure it's not a socket or directory
                    // (in other words, make sure it's an actual file)
                    return !(S_ISDIR(fi.st_mode)) &&
                        !(S_ISSOCK(fi.st_mode));
                #else
                    return !(S_ISDIR(fi.st_mode));
                #endif
            }
            return false;
        #endif
    #else
        struct stat fi;
        if (stat(file, &fi) == 0) {
            #if defined(S_ISSOCK)
                return !(S_ISDIR(fi.st_mode)) &&
                    !(S_ISSOCK(fi.st_mode));
            #else
                return !(S_ISDIR(fi.st_mode));
            #endif
        }
        return false;
    #endif
}

bool dir_exists(const char* folder)
{
    if (folder == NULL) { return false; }
    #if defined(OS_WIN)
        #if defined(WIN_API)
            // if you want the WinAPI, versus CRT
            if (strnlen(folder, MAX_PATH+1) > MAX_PATH) {
                // ... throw error here or ...
                return false;
            }
            DWORD res = GetFileAttributesA(folder);
            return (res != INVALID_FILE_ATTRIBUTES &&
                (res & FILE_ATTRIBUTE_DIRECTORY));
        #else
            struct stat fi;
            if (_stat(folder, &fi) == 0) {
                return (S_ISDIR(fi.st_mode));
            }
            return false;    
        #endif
    #else
        struct stat fi;
        if (stat(folder, &fi) == 0) {
            return (S_ISDIR(fi.st_mode));
        }
        return false;
    #endif
}

要为Windows构建它,只需为该构建定义OS_WIN;另外,如果要坚持使用完整的WinAPI,而不是使用Windows CRT,则可以定义WIN_API

要检查给定的路径是文件还是目录,可以使用以下代码:

bool is_file(const char* path)
{
    return file_exists(path) && !dir_exists(path);
}

bool is_dir(const char* path)
{
    return dir_exists(path) && !file_exists(path);
}

您显然可以将代码更改为适合您需要的任何内容,但这应该可以指导您在Windows / macOS / * nix系统上构建代码的方向。

我希望能对您有所帮助。