【问题标题】:Displaying all the files in a folder using win32 C++使用win32 C++显示文件夹中的所有文件
【发布时间】:2021-04-12 17:22:39
【问题描述】:

我有一个包含大约 9 个文件的文件夹,当按下按钮时,我试图让我的代码显示文件夹中每个文件的消息框以及文件名。出于某种原因,它只显示文件夹中最后一个文件的消息框,然后给我错误:“查找文件时出错。”它来自我创建的错误处理程序 if (fileError != ERROR_NO_MORE_FILES)。我不确定为什么它不显示所有文件名并给我一个错误。我的代码的相关部分如下:

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

TCHAR file_buff[200];
TCHAR file_buff2[200];
TCHAR file_buff3[200];
WIN32_FIND_DATA FindFileData;
HANDLE hFind;
DWORD fileError_initial = 0;
DWORD fileError = 0;

按下应该给我所有消息框的按钮:

case IDC_BUTTON_RUN:

    hFind = FindFirstFile(L"C:\\Users\\sallen\\Desktop\\Folder1\\*", &FindFileData);

    fileError_initial = GetLastError();

    if (hFind == INVALID_HANDLE_VALUE)
    {
        wsprintfW(file_buff, L"No files were found.\n Error: %s.", fileError_initial);
        MessageBox(NULL, file_buff, L"File Search Error", 0);
        return fileError_initial;
    }

    else
    {
        while (FindNextFile(hFind, &FindFileData) != 0);
        {
            wsprintf(file_buff2, L"The first file found is %s.\n", FindFileData.cFileName);
            MessageBox(hWnd, file_buff2, L"File Name", 0);
        }

        fileError = GetLastError();
        if (fileError != ERROR_NO_MORE_FILES)
        {
            wsprintfW(file_buff3, L"Error finding files. %s", fileError);
            MessageBox(hWnd, file_buff3, L"File Search Error", 0);
        }

    }
    FindClose(hFind);
    return fileError;

    break;

【问题讨论】:

  • 1. else 有什么意义? 2.FindFirstFile返回第一个文件。你忽略它。 3. MS Docs 网站上有一个例子。
  • 首先,您不会看到有关您找到的第一个文件的消息框,因为您在打印有关第一个文件的信息之前调用了FindNextFile。其次,你怎么知道你只看到目录中的最后一个文件? FindFIrstFIle/FindNextFIle 不一定按字母顺序返回文件。
  • 我希望它循环遍历所有文件,直到不再循环遍历。因为我在做“while (FindNextFile(hFind, &FindFileData) != 0);”,所以 while 循环不会这样做吗?当我在调用 FindFirstFile 后打印出文件名时,它给了我“。”我查看了 MS Docs 网站上的示例。
  • 我按照docs.microsoft.com/en-us/windows/win32/fileio/… 的示例做了,但由于某种原因它对我不起作用
  • 我已将其更新为使用 do-while 循环,这可以正常工作并按顺序获取所有文件,但它也会找到文件“。”和“..”在文件夹中的实际文件之前。当我没有任何名称为“。”的文件时,为什么会这样做?和“..”?

标签: c++ file winapi find messagebox


【解决方案1】:

您的while 声明上有一个错误的;

while (FindNextFile(hFind, &FindFileData) != 0); // <-- here

因此,您循环而不处理FindFileData,直到FindNextFile() 失败,然后您处理最后报告的FindFileData 数据。该显示最终会清除失败的FindNextFile() 报告的错误代码,这就是为什么当您实际检索错误代码时不再是ERROR_NO_MORE_FILES

你需要删除那个错误的;

另外,您应该改用do..while 循环。使用while 循环将跳过FindFirstFile() 报告的第一个文件。

试试这个:

case IDC_BUTTON_RUN:

    hFind = FindFirstFile(L"C:\\Users\\sallen\\Desktop\\Folder1\\*", &FindFileData);
    if (hFind == INVALID_HANDLE_VALUE)
    {
        fileError = GetLastError();
        if (fileError == ERROR_FILE_NOT_FOUND)
        {
            fileError = 0;
            MessageBox(NULL, L"No files were found.", L"File Search Error", MB_OK | MB_ICONWARNING);
        }
        else
        {
            wsprintfW(file_buff, L"Error finding files. %d", fileError);
            MessageBox(hWnd, file_buff, L"File Search Error", MB_OK | MB_ICONERROR);
        }
        return fileError;
    }

    do
    {
        if ((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
        {      
            MessageBox(hWnd, FindFileData.cFileName, L"File Name", MB_OK | MB_ICONINFORMATION);
        }
    }
    while (FindNextFile(hFind, &FindFileData));

    fileError = GetLastError();
    FindClose(hFind);

    if (fileError != ERROR_NO_MORE_FILES)
    {
        wsprintfW(file_buff, L"Error finding files: %d", fileError);
        MessageBox(hWnd, file_buff, L"File Search Error", MB_OK | MB_ICONERROR);
    }
    else
        fileError = 0;

    return fileError;

更新:要处理子文件夹,您必须将代码移动到递归函数中,例如:

DWORD SearchFolder(LPCTSTR folder)
{
    WIN32_FIND_DATA FindFileData;
    TCHAR mask[MAX_PATH+3], filePath[MAX_PATH];
    DWORD dwError, dwResult;

    PathCombine(mask, folder, L"*");

    HANDLE hFind = FindFirstFile(mask, &FindFileData);
    if (hFind == INVALID_HANDLE_VALUE)
        return GetLastError();

    dwResult = ERROR_NO_FILES_FOUND;

    do
    {
        if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
        {
            if (lstrcmp(FindFileData.cFileName, ".") == 0 || lstrcmp(FindFileData.cFileName, "..") == 0)
                continue;

            PathCombine(filePath, folder, FindFileData.cFileName);           
            dwError = SearchFolder(filePath);

            if (dwError != NO_ERROR && dwError != ERROR_NO_FILES_FOUND) {
                SetLastError(dwError);
                break;
            }
        }
        else
        {      
            // do something with FindFileData.cFileName ...

            PathCombine(filePath, folder, FindFileData);
            ...

            dwResult = NO_ERROR;
        }
    }
    while (FindNextFile(hFind, &FindFileData));

    dwError = GetLastError();
    FindClose(hFind);

    if (dwError != ERROR_NO_MORE_FILES)
        return dwError;

    return dwResult;
}

...

case IDC_BUTTON_RUN:
{
    DWORD dwResult = SearchFolder(L"C:\\Users\\sallen\\Desktop\\Folder1\\");
    if (dwResult != NO_ERROR)
    {
        if (dwResult == ERROR_NO_FILES_FOUND) {
            MessageBox(NULL, L"No files were found.", L"File Search Error", MB_OK | MB_ICONWARNING);
        }
        else {
            swprintf(file_buff, L"Error finding files. %u", dwError);
            MessageBox(hWnd, file_buff, L"File Search Error", MB_OK | MB_ICONERROR);
        }
    }
    return dwError;
}

【讨论】:

  • @drescherjm 我已经恢复了
  • FindFirstFile() 和 FindNextFile() 是否也可以在目录中查找文件夹以及在文件夹中查找文件夹,以及这些文件夹中的所有文件?
  • 是的,但是您必须递归地进行这些调用。 FindFileData.dwFileAttributes 将在找到匹配文件夹时设置FILE_ATTRIBUTE_DIRECTORY 属性,FindFileData.cFileName 将拥有文件夹名称。忽略"."".." 文件夹,并为找到的每个文件夹调用一个新的Find(First|Next)File() 循环。
  • 在你上面的例子中,“(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0”,但是为了找到文件夹和文件,我做了 FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 但这只是找到文件夹,而不是文件。
  • @Sophia 最初的例子是只寻找文件而忽略文件夹。查看我刚刚发布的更新,它同时搜索文件夹和文件
猜你喜欢
  • 1970-01-01
  • 2021-04-29
  • 1970-01-01
  • 1970-01-01
  • 2020-02-03
  • 1970-01-01
  • 2021-10-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多