带空格的FindNextFile失败

3

我写了一段简单的代码来对每个文件夹(包括子文件夹)中的所有文件执行某些操作。 当路径中包含空格字符时,程序会崩溃并调用INVALID_HANDLE_VALUE。以下是该函数:

int dirListFiles(char* startDir)
{
    HANDLE hFind;
    WIN32_FIND_DATAA  wfd;
    char path[MAX_PATH];

    sprintf(path, "%s\\*", startDir);

    std::string fileName;
    std::string s_path = startDir;
    std::string fullPath;

    fprintf(stdout, "In Directory \"%s\"\n\n", startDir);

    if ((hFind = FindFirstFileA(path, &wfd)) == INVALID_HANDLE_VALUE)
    {
        printf("FindFirstFIle failed on path = \"%s\"\n", path);
        abort();
    }

    BOOL cont = TRUE;
    while (cont == TRUE)
    {
        if ((strncmp(".", wfd.cFileName, 1) != 0) && (strncmp("..", wfd.cFileName, 2) != 0))
        {
            if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
            {
                sprintf(path, "%s\\%s", startDir, wfd.cFileName);
                dirListFiles(path);
            }
        else
        {
            fileName = wfd.cFileName;
            fullPath = s_path + "\\" + fileName;    

            std::string fileExt = PathFindExtension(fullPath.c_str());
            if (fileExt == ".cpp")
            {
                ... Some operation on file
            }
        }
    }
    cont = FindNextFile(hFind, &wfd);
}

FindClose(hFind);

例如,如果FindNextFile想要打开带有空格的文件名Program Files (x86),那么会导致错误并使程序退出。我该怎么做来支持空格?问题出在哪里?

1
性能差异很大。 - RbMm
1
代码中存在许多错误。例如,您在长路径(> MAX_PATH)等方面失败了。 - RbMm
2
@AliSepehri-Amin - 你只需要分配一次最大路径长度缓冲区,即0x8000 wchar(64kb)。之后,你就不需要再分配任何名称了。你只需要将文件名附加到缓冲区的当前位置即可。 - RbMm
2
@AliSepehri-Amin - 你认为有什么不同吗?你可以在第一次函数调用之前将其分配为堆栈中的本地变量,例如 WCHAR buf[0x8000]; - RbMm
1
WIN32_FIND_DATA最好在递归函数调用之前声明并将其作为指针传递,而不是在函数内部声明(结构体太大,无法进行递归调用)。 - RbMm
显示剩余10条评论
1个回答

1

空格是目录和文件名中合法的字符。

首先,我建议稍微修改你的代码:

if ((hFind = FindFirstFileA(path, &wfd)) == INVALID_HANDLE_VALUE)
{
    printf("FindFirstFIle failed on path = \"%s\". Error %d\n", path, GetLastError());
    return 0; // I think you shouldn't abort on error, just skip this dir.
}

现在检查你的程序报告的错误代码。

对于某些路径,我收到了错误#5(访问被拒绝)的错误代码。例如:

c:\Program Files (x86)\Google\CrashReports\*
c:\ProgramData\Microsoft\Windows Defender\Clean Store\*
c:\Windows\System32\config\*

有两个代码为#123(无效名称)的案例,适用于FindFirstFileA无法管理的路径名。为了更正这种行为,最好使用函数FindFirstFileW的宽版本。请参见c++ folder only search的两个答案。对于新的Windows应用程序,应使用API的宽版本,并在需要时使用 MultiByteToWideCharWideCharToMultiByte 进行转换。

您还有逻辑错误。代码跳过以点开头的所有目录和文件。


4
假设出现错误代码“ERROR_INVALID_NAME”,表示当前 ANSI 代码页无法表示路径名,这可以通过使用 Unicode 轻松解决。即使没有出现该错误,文件 I/O 应始终使用 Unicode。这样更安全、更快,而且(潜在地)可以放松许多长度限制。 - IInspectable

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