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

Check if object at a path is a file or directory cross platform?

您可以使用 stat() function to check if an object is a file or directory, like this. My issue is, <sys/stat.h> isn't on Windows, and I'm not sure what the Windows equivalent or Windows function is. This question is how do I do this,但特别是以跨平台的方式。

在避免条件编译代码的同时,如何跨平台检查路径中的对象是 C 中的文件还是目录?虽然有一个almost identical question,但没有人回答,对我没有帮助,作者被删除,问题无法维护。

据我了解,fopen() 是跨平台的,opendir()readdir()scandir() 等也是,所以为什么不简单地检查一个对象是否是一个文件或目录是跨平台的?如果没有办法,条件编译的代码是唯一的办法,我怎么办 Windows?

不幸的是,在 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 系统上构建代码所需的方向前进。

希望能帮到你。