【问题标题】:How to check if any file exist in specific folder?如何检查特定文件夹中是否存在任何文件?
【发布时间】:2018-11-17 17:10:08
【问题描述】:

我正在使用CreateProcess 来复制文件。我也可以捕捉到不同的错误,如果 PC 离线,如果目录不存在。 这是我遇到的问题:如果所有复制都成功,则返回 0 作为错误代码;如果源文件夹中的文件为零,则返回 0,因此不进行复制。我必须检测源文件夹中是否没有文件。如何在 MFC VC++ 2013 中做到这一点?

我花了几个小时尝试不同的解决方案,但我的知识还不足以实现我在互联网上找到的所有内容。所以我必须要代码,然后我就明白了。提前谢谢你。

这是我使用的代码:

temp_dest = _T("/min /c xcopy \"D:\\Test\\*.*\" \"") + m_destination + _T("\" /Y /E /Q");
LPTSTR temp_dest2 = (LPTSTR)(LPCTSTR)temp_dest;
STARTUPINFO            sinfo;
PROCESS_INFORMATION    pinfo;
memset(&sinfo, 0, sizeof(STARTUPINFO));
memset(&pinfo, 0, sizeof(PROCESS_INFORMATION));
sinfo.dwFlags = STARTF_USESHOWWINDOW;
sinfo.wShowWindow = SW_HIDE;
BOOL bSucess = CreateProcess(L"C:\\Windows\\System32\\cmd.exe", temp_dest2, NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE, NULL, NULL, &sinfo, &pinfo);
DWORD dwCode;
TerminateProcess(pinfo.hProcess, 2);
GetExitCodeProcess(pinfo.hProcess, &dwCode);
TCHAR msg2[100];
StringCbPrintf(msg2, 100, TEXT("%X"), dwCode); 
MessageBox(msg2, (LPCWSTR)L"DWCode 2", MB_OK | MB_ICONERROR);
if (dwCode == 4)
{
    MessageBox((LPCWSTR)L"DW 4", (LPCWSTR)L"Path not found", MB_OK | MB_ICONERROR);
}
if (dwCode == 2)
{
    MessageBox((LPCWSTR)L"DW 4", (LPCWSTR)L"PC Offline", MB_OK | MB_ICONERROR);
}

【问题讨论】:

  • c++17 有<filesystem> 从代码中复制而不是依赖外部命令。
  • 这会像 bat 文件一样简单。有什么理由需要在 C++ 中?
  • 看看你能不能摆脱_T和所有TCHAR的混乱。使用 Unicode 版本,而不是当前的 Wide 和 T 字符组合,并完成它。这样可以减少令人讨厌的惊喜。
  • 如果全部复制成功则返回0作为错误码,如果源文件夹中有零个文件也返回0,因此不进行复制。首先,如何那是失败?如果源文件夹中没有文件,则无需进行复制。其次,您的整个设计是TOCTOU bug。如果任何文件在您检查它们存在后被删除,会发生什么?如果在您没有找到文件后添加文件会怎样?
  • "我正在使用 CreateProcess 复制文件" - 为什么?您可以使用SHFileOperation()IFileOperation 代替,无需使用单独的进程。

标签: c++ windows file winapi mfc


【解决方案1】:

您可以使用WIN32函数GetFileAttributes(..)来检查文件是否存在:

if (GetFileAttributes("C:\\test.txt") != INVALID_FILE_ATTRIBUTES)
{
    /* C:\test.txt is existing */
}

另一种方法可能是尝试打开文件(如果成功则再次关闭它)。

【讨论】:

  • @Luke Thomsen 如果文件名未知,我可以使用 GetFileAttributes 吗?使用 *.* 之类的东西
  • 不,你不能。如果您想搜索 . 之类的模式,请查看 FindFirstFile(..) 和 FindNextFile(..) 函数,它们允许您搜索目录中的现有文件。
  • @Luke Thomsen 好的,我现在明白了...我终于找到了...因为源路径是静态的,但文件名是动态的,我可以使用此代码WIN32_FIND_DATA findFileData; HANDLE hFind; hFind = FindFirstFile(L"C:\\*.*", &findFileData); if (hFind != INVALID_HANDLE_VALUE) { MessageBox(findFileData.cFileName, (LPCWSTR)L"Fajl 1", MB_OK | MB_ICONERROR);}
  • 请注意,当文件存在但您不存在时,GetFileAttributes() 可能会因ERROR_ACCESS_DENIED 而失败可能(尽管不太可能)有权读取其属性。因此,您应该检查该条件,例如:if ((GetFileAttributes("C:\\test.txt") != INVALID_FILE_ATTRIBUTES) || (GetLastError() == ERROR_ACCESS_DENIED)) 与打开文件相同。
  • @RemyLebeau 感谢您提供的信息,但是(我认为)访问被拒绝是不可能的,因为在复制之前,我正在为管理员帐户 temp_cred = _T("/min /c cmdkey /add:PC_NAME.SUBDOMAIN.DOMAIN.local /user:admin /pass:text"); ShellExecute(GetSafeHwnd(),"open",L"C:\\Windows\\System32\\cmd.exe",temp_cred,NULL,SW_HIDE); 添加 Windows 凭据
【解决方案2】:

如果可以使用C++17中引入的<filesystem>头文件中的directory_iterator

bool IsEmptyDirectory( const wchar_t* dir )
{
    return std::filesystem::directory_iterator( std::filesystem::path( dir ) )
            == std::filesystem::directory_iterator();
}

可能需要std::experimental::filesystem 而不是std::filesystem

我尝试将其移植到 VC 2013,但似乎只有 char 版本可以编译

bool IsEmptyDirectory( const char* dir )
{
    return std::tr2::sys::directory_iterator( std::tr2::sys::path( dir ) )
            == std::tr2::sys::directory_iterator();
}

如果您想(或必须)使用 WinAPI:

bool IsEmptyDirectory( const wchar_t* dir )
{
    wstring mask( dir);
    mask += L"\\*";

    WIN32_FIND_DATA data;
    HANDLE  find_handle = FindFirstFile( mask.c_str(), &data );
    if ( find_handle == INVALID_HANDLE_VALUE )
    {
        // Probably there is no directory with given path.
        // Pretend that it is empty.
        return true;
    }

    bool empty = true;
    do
    {
        // Any entry but . and .. means non empty folder.
        if ( wcscmp( data.cFileName, L"." ) != 0 && wcscmp( data.cFileName, L".." ) != 0 )
            empty = false;
    } while ( empty && FindNextFile( find_handle, &data ) );

    FindClose( find_handle );

    return empty;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-09
    • 1970-01-01
    • 2011-11-15
    • 2021-09-19
    • 1970-01-01
    • 2019-03-26
    相关资源
    最近更新 更多