我的基本问题是这段代码几乎总是抛出异常:
bool DirectoryRange::isDirectory() const
{
struct stat s;
stat(ep->d_name, &s);
#if defined(__linux__)
if((S_ISDIR(s.st_mode) != 0) != (ep->d_type == DT_DIR))
{
throw std::logic_error("Directory is not directory");
}
#endif
return S_ISDIR(s.st_mode);
}
bool DirectoryRange::isFile() const
{
struct stat s;
stat(ep->d_name, &s);
#if defined(__linux__)
if((S_ISREG(s.st_mode) != 0) != (ep->d_type == DT_REG))
{
throw std::logic_error("File is not file");
}
#endif
return S_ISREG(s.st_mode);
}
检查dirent值是不可移植的,但是得到了正确的答案;虽然stat是错误的,但是便于携带。
那么,如果stat似乎无法正常工作,我如何便携地检查目录?
答案 0 :(得分:0)
对于初学者,S_ISDIR
为not a macro that returns a boolean value:
如果测试为真,则宏评估为非零值,如果为,则为0 测试是错误的。
...
S_ISDIR(m) - 测试目录。
(强调我的)。对bool
的显式转换是错误的,并且没有任何用处。使用此宏(和其他S_..
宏)的正确方法是:
if(S_ISDIR(s.st_mode) == 0)
{
throw std::logic_error("Directory is not a Directory");
}
答案 1 :(得分:0)
这似乎最可靠:
bool DirectoryRange::isDirectory() const
{
#if defined(__linux__) || (defined(__APPLE__) && defined(__MACH__))
return ep->d_type == DT_DIR;
#else
auto path = syspath();
DIR * dp = opendir(path.c_str());
if(dp) closedir(dp);
return dp;
#endif
}
bool DirectoryRange::isFile() const
{
#if defined(__linux__) || (defined(__APPLE__) && defined(__MACH__))
return ep->d_type == DT_REG;
#else
auto path = syspath();
FILE * fp = fopen(path.c_str(), "r");
if(fp) fclose(fp);
return fp;
#endif
}