如何在C中检查Windows上是否存在目录?

时间:2011-06-02 17:57:53

标签: c windows winapi

问题

在Windows C应用程序中,我想验证传递给函数的参数,以确保指定的路径存在。*

如何在C中检查Windows上是否存在目录?

*我了解你可以进入竞争条件,在你检查存在的时间和使用它不再存在的路径的时间之间,但我可以处理。

附加背景

当权限发挥作用时,明确知道目录是否存在可能会变得棘手。在尝试确定目录是否存在时,该进程可能无权访问目录或父目录。 这可以满足我的需求。如果目录不存在或者我无法访问它,则在我的应用程序中都将两者视为无效路径故障,因此我不需要区分。如果您的解决方案提供了这种区别,则(虚拟)奖励积分。

C语言,C运行时库或Win32 API中的任何解决方案都很好,但理想情况下我想坚持常用的库(例如kernel32,user32等)并避免涉及加载非的解决方案标准库(如Shlwapi.dll中的PathFileExists)。如果您的解决方案是跨平台的,那么(虚拟)奖励积分。

相关

How can we check if a file Exists or not using Win32 program?

5 个答案:

答案 0 :(得分:84)

做这样的事情:

BOOL DirectoryExists(LPCTSTR szPath)
{
  DWORD dwAttrib = GetFileAttributes(szPath);

  return (dwAttrib != INVALID_FILE_ATTRIBUTES && 
         (dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}

GetFileAttributes()方法包含在Kernel32.dll中。

答案 1 :(得分:22)

这是一个完全与平台无关的解决方案(使用标准C库)

编辑:要在Linux中进行编译,请将<io.h>替换为<unistd.h>,将_access替换为access。对于真正的平台无关解决方案,请使用Boost FileSystem库。

#include <io.h>     // For access().
#include <sys/types.h>  // For stat().
#include <sys/stat.h>   // For stat().

bool DirectoryExists( const char* absolutePath ){

    if( _access( absolutePath, 0 ) == 0 ){

        struct stat status;
        stat( absolutePath, &status );

        return (status.st_mode & S_IFDIR) != 0;
    }
    return false;
}

支持MBCS和UNICODE构建的Windows特定实现:

#include <io.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <tchar.h>

BOOL directory_exists( LPCTSTR absolutePath )
{
  if( _taccess_s( absolutePath, 0 ) == 0 )
  {
    struct _stat status;
    _tstat( absolutePath, &status );
    return (status.st_mode & S_IFDIR) != 0;
  }

  return FALSE;
}

答案 2 :(得分:9)

如果您可以使用Shell轻量级API(shlwapi.dll)链接,则可以使用PathIsDirectory function

答案 3 :(得分:4)

另一个选项是shell函数PathFileExists()

PathFileExists() documentation

此函数&#34;确定文件系统对象(如文件或目录)的路径是否有效。&#34;

答案 4 :(得分:0)

所以,这个问题充满了边缘情况。真正的答案是这样的:

BOOL DirectoryExists(LPCTSTR szPath, BOOL *exists)
{
  *exists = FALSE;
  size_t szLen = _tcslen(szPath);
  if (szLen > 0 && szPath[szLen - 1] == '\\') --szLen;
  HANDLE heap = GetProcessHeap();
  LPCTSTR szPath2 = HeapAlloc(heap, 0, (szlen + 3) * sizeof(TCHAR));
  if (!szPath2) return FALSE;
  CopyMemory(szPath2, szPath, szLen * sizeof(TCHAR));
  szPath2[szLen] = '\\';
  szPath2[szLen + 1] = '.';
  szPath2[szLen + 2] = 0;
  DWORD dwAttrib = GetFileAttributes(szPath2);
  HeapFree(heap, 0, szPath2);

  if (dwAttrib != INVALID_FILE_ATTRIBUTES) {
    *exists = TRUE; /* no point checking FILE_ATTRIBUTE_DIRECTORY on "." */
    return TRUE;
  }
  /*
   * If we get anything other than ERROR_PATH_NOT_FOUND then something's wrong.
   * Could be hardware IO, lack of permissions, a symbolic link pointing to somewhere
   * you don't have access, etc.
   */
  return GetLastError() != ERROR_PATH_NOT_FOUND;
}

DirectoryExists 的正确结果是三态。共有三种情况,您需要处理所有情况。要么存在,要么不存在,或者您无法检查。我在生产中丢失了数据,因为 SAN 向检查函数返回 NO,然后让我在下一行代码中创建一些破坏它的东西。不要犯微软在 C# 中设计 File.Exists() API 时犯过的错误。

但是,我看到很多检查都是非常有用的。不要像if (目录不存在) CreateDirectory()那样写;只需写CreateDirectory() if (GetLastError() != 0 && GetLastError() != ERROR_ALREADY_EXISTS。或者与 RemoveDirectory() 相反;只需将其删除并检查是否没有错误或未找到路径。