如何使用Win32程序检查文件是否存在?

81

我如何使用Win32程序检查文件是否存在?我正在为Windows Mobile应用程序工作。


3
std::filesystem::exists() 是 C++17 及以上版本中的函数,其功能为判断给定路径是否存在。 - Sahil Singh
9个回答

224

7
因为有一个简短的代码示例,所以我点了一个赞。代码示例是入门的时间节省器。 - nalply
1
@Bitterblue:是的,这是我能找到的最快的速度。 - Cameron
在C++中,该表达式返回布尔值,因此布尔返回是可以的。 - paulm
2
虽然 GetFileAttributes() 可能由于文件不存在以外的错误条件而返回 INVALID_FILE_ATTRIBUTES - Jonathan Wood
"相关的"? "复制自。" - MD XF
显示剩余4条评论

39

您可以使用函数GetFileAttributes。如果文件不存在,它会返回0xFFFFFFFF


17
“GetFileAttributes”在Windows代码中为何是首选方法,雷蒙德·陈(Raymond Chen)的博客分享了有趣的历史:http://blogs.msdn.com/b/oldnewthing/archive/2007/10/23/5612082.aspx - Zach Burlingame
2
你需要检查对象是否为目录。 - David Heffernan
12
如果文件不存在,实际上会返回“INVALID_FILE_ATTRIBUTES”。在64位系统中可能是“0xFFFFFFFFFFFFFFFF”。 - Andreas Spindler
7
@AndreasSpindler,由于返回类型是 DWORD,它如何返回 0xFFFFFFFFFFFFFFFF - Ajay
2
更新链接到Raymond Chen的博客: https://devblogs.microsoft.com/oldnewthing/20071023-00/?p=24713 - Ray

29

您可以调用FindFirstFile函数。

这是我刚刚编写的一个示例:

#include <windows.h>
#include <tchar.h>
#include <stdio.h>

int fileExists(TCHAR * file)
{
   WIN32_FIND_DATA FindFileData;
   HANDLE handle = FindFirstFile(file, &FindFileData) ;
   int found = handle != INVALID_HANDLE_VALUE;
   if(found) 
   {
       //FindClose(&handle); this will crash
       FindClose(handle);
   }
   return found;
}

void _tmain(int argc, TCHAR *argv[])
{
   if( argc != 2 )
   {
      _tprintf(TEXT("Usage: %s [target_file]\n"), argv[0]);
      return;
   }

   _tprintf (TEXT("Looking for file is %s\n"), argv[1]);

   if (fileExists(argv[1])) 
   {
      _tprintf (TEXT("File %s exists\n"), argv[1]);
   } 
   else 
   {
      _tprintf (TEXT("File %s doesn't exist\n"), argv[1]);
   }
}

你忘记调用 FindClose 函数了。而且你不能从一个 void 函数中返回值。 - David Heffernan
4
需要检查FILE_ATTRIBUTE_DIRECTORY。原文是“Half corrected.”,可能有些上下文缺失。 - David Heffernan
2
请参考其他答案以找到更好的解决方法。此外,由于在fileExists()中使用了argv[1],因此代码本身甚至无法编译。 - Christian Aichinger
3
不良解决方案;GetFileAttributes()更好。 - trojanfoe
2
GetFileAttributes 是一行代码。 - Matt Clarkson
4
假设 file = "*", 即使没有名为 * 的文件,这可能会返回 true - Felix Dombek

20

那么我们可以简单地这样做:

#include <io.h>
if(_access(path, 0) == 0)
    ...   // file exists

Pierre,你是怎么找到这个函数的?有参考资料吗? - Buddhika Chaturanga
2
@Buddhika Chaturanga 我在80年代开始使用它,当时是在Borland Turbo C中。在更高级的“CreateFile”出现之前,这是检查文件是否存在的唯一方法。它被埋藏在Visual Studio文档中。 - Pierre
我不得不使用 if (_waccess(path.c_str(), 0) == 0)... 对于文件和文件夹都可以正常工作,谢谢@Pierre。 - mourad

10
另一个选择是:'PathFileExists'
但我可能会选择使用GetFileAttributes

2
另外,PathFileExists 需要使用 "Shlwapi.dll"(在某些 Windows 版本中不可用),并且比 GetFileAttributes 稍微慢一些。 - Bitterblue
但它并不告诉你文件或目录是否存在。 - Jonathan Wood
顺便提一下,PathFileExists只是GetFileAttributes的包装器,还带有额外的SetErrorMode(SEM_FAILCRITICALERRORS)包装器。 - Alex

1

我遇到了同样的问题,在另一个论坛中找到了这段简短的代码,使用了GetFileAttributes方法。

DWORD dwAttr = GetFileAttributes(szPath);
if (dwAttr == 0xffffffff){

  DWORD dwError = GetLastError();
  if (dwError == ERROR_FILE_NOT_FOUND)
  {
    // file not found
  }
  else if (dwError == ERROR_PATH_NOT_FOUND)
  {
    // path not found
  }
  else if (dwError == ERROR_ACCESS_DENIED)
  {
    // file or directory exists, but access is denied
  }
  else
  {
    // some other error has occured
  }

}else{

  if (dwAttr & FILE_ATTRIBUTE_DIRECTORY)
  {
    // this is a directory
  }
  else
  {
    // this is an ordinary file
  }
}

其中szPath是文件路径。


0
使用 OpenFile 函数并设置 uStyle 参数为 OF_EXIST
if (OpenFile(path, NULL, OF_EXIST) == HFILE_ERROR)
{
    // file not found
}
// file exists, but is not open

记住,在使用OF_EXIST时,文件在OpenFile成功后不会打开。根据Win32文档:

含义
OF_EXIST (0x00004000) 打开一个文件然后关闭它。使用此选项来测试文件是否存在。

请参阅文档: https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-openfile


0

你可以尝试打开文件。如果失败了,那通常意味着文件不存在。


我会选择使用CreateFile -> CloseHandle。这是最简单和最便宜的方法。 - OSH
7
如果文件存在但用户没有足够的权限打开文件,文件打开也会失败。如今,这是非常普遍的情况。 - JackLThornton
更不用说它并不是最便宜的,因为文件可以在网络共享上,这会为每个调用增加延迟,并且使用CloseHandle需要两个调用而不是一个。 - Igor Levicki

-2

另一种更通用的非Windows方式:

static bool FileExists(const char *path)
{
    FILE *fp;
    fpos_t fsize = 0;

    if ( !fopen_s(&fp, path, "r") )
    {
        fseek(fp, 0, SEEK_END);
        fgetpos(fp, &fsize);
        fclose(fp);
    }

    return fsize > 0;
}

如果你打算使用fopen等函数,那么最好直接使用_access(0) - Rob K
2
@RobK 这种方法的小优点是跨平台,而 _access 不是。真正的问题在于它会返回零长度文件不存在的信息... - Perkins
fopen_s是Microsoft特有的,除了将0字节文件声明为不存在之外,这个错误的代码还会在无法打开文件(权限、共享)时失败。 - Igor Levicki

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接