检查路径上的对象是不是是跨平台的文件或目录?
Posted
技术标签:
【中文标题】检查路径上的对象是不是是跨平台的文件或目录?【英文标题】:Check if object at a path is a file or directory cross platform?检查路径上的对象是否是跨平台的文件或目录? 【发布时间】:2020-07-12 02:39:04 【问题描述】:您可以使用stat()
函数来检查对象是文件还是目录,例如this。我的问题是,<sys/stat.h>
不在 Windows 上,我不确定 Windows 等效或 Windows 功能是什么。这个问题是我该怎么做this,但具体是跨平台的方式。
在避免条件编译代码的同时,如何跨平台检查路径中的对象是 C 中的文件还是目录?虽然有一个almost identical question,但它没有帮助我,因为它没有答案,并且作者已被删除,因此无法维护问题。
据我了解,fopen()
是跨平台的,opendir()
、readdir()
、scandir()
等也是如此,那么为什么不简单地检查对象是否是文件或目录是跨平台的呢?如果没有办法,而条件编译的代码是唯一的办法,我在windows下怎么办?
【问题讨论】:
在标准 C 中没有办法。但条件编译是在 Windows 上完成的,而在其他操作系统上stat()
可能会覆盖 99% 以上的(非嵌入式)使用。
@Shawn 那么它在 Windows 上是如何完成的?
打败我;我不会做很多 Windows 编程。
GetFileAttributes()
和 GetFileType()
似乎是相关功能。
【参考方案1】:
不幸的是,在 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 系统上构建代码所需的方向前进。
希望能帮到你。
【讨论】:
什么是#include <fcntl.h>
,为什么我需要?你能澄清一下吗?
@user13783520 .. 抱歉,fcntl.h
包含其他用于 I/O 控制的功能 .. 您不需要此特定代码;修改答案以反映这一点。以上是关于检查路径上的对象是不是是跨平台的文件或目录?的主要内容,如果未能解决你的问题,请参考以下文章