-3

我尝试编写在当前目录及其子目录中查找所有文件的应用程序。我有下一个问题我无法完全理解

  1. 在我的情况下我需要如何使用递归GetFiles()函数,以及
  2. 我需要在PathCreator()函数中动态分配的空闲内存。当我仅针对某些目录(没有子目录)测试该程序时,它可以工作(查看 中的注释代码_tmain())。但是当我尝试获取所有文件时,就会崩溃。

这是我的代码:

// ConsoleApplication1.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <windows.h>
#include <iostream>
#define SIZE 300

int is_directory(wchar_t *p)
{
    wchar_t temp[300];
    int i;
    i = 0;
    while(*p != '\0')
    {
        temp[i] = *p;
        p++;
        i++;
    }
    temp[i] = '\\';
    i++;
    temp[i] = '\0';
    WIN32_FIND_DATA file;
    HANDLE search_hendle = FindFirstFile(temp, &file);
    long error = GetLastError();
    if(error == 267)
    {
        return 0;
    }
    else
    {
        return 1;
    }
}


wchar_t *PathCreator(wchar_t *dir, wchar_t *fileName)
{
    wchar_t* path = new wchar_t[SIZE];
    int j = 0;
    while(j < SIZE)
    {
        path[j] = '\0';
        j++;
    }
    int i;
    i = 0;
    while(*dir != '*' && *dir != '\0')
    {
        path[i] = *dir;
        i++;
        dir++;
    }
    wchar_t *t = fileName;  
    while(*t != '\0')
    {
        path[i] = *t;
        i++;
        t++;
    }
    path[i] = '\0';
    return path;
} 

wchar_t* allFlsArr[SIZE];
int i = 0;
wchar_t **GetAllFiles(wchar_t* dir)
{
    WIN32_FIND_DATA file;
    HANDLE search_hendle = FindFirstFile(dir, &file);
    if(search_hendle)
    {
        do
        {
            wchar_t *p = PathCreator(dir,file.cFileName);
            allFlsArr[i++] = p;
        }
        while(FindNextFile(search_hendle, &file));
        allFlsArr[i] = '\0';
    }
    CloseHandle(search_hendle);
    return allFlsArr;
}

void GetFiles(wchar_t *dir)
{
    wchar_t **filePaths = 0;
    filePaths = GetAllFiles(dir);
    int  i = 0;
    while(filePaths[i] != '\0'){
        if(!is_directory(filePaths[i]))
        {
            std::wcout << filePaths[i] << std::endl;
        }
        else
        {
            GetAllFiles(filePaths[i]);
        }
    }
    delete [] filePaths;
}
int _tmain(int argc, _TCHAR* argv[])
{
    /*wchar_t **wch = GetAllFiles(L"C:\\*");
    int i = 0;
    while( *wch != '\0')
    {
        std::wcout << *wch << std::endl;
        wch++;
    }*/
    GetFiles(L"C:\\*");
}
4

1 回答 1

3

首先,我想知道为什么您从不使用wcscpy,wcscat或 ... 之类的函数,而总是手动进行所有字符串和缓冲区操作!?但除此之外,您的代码中还有一些问题:

  • 您使用单个宽字符串指针数组(allFlsArr)将结果返回GetAllFiles给调用者,当您迭代该结果时,您将GetAllFiles再次调用将覆盖的结果allFlsArr

  • 您正在释放GetAllFiles使用的结果,delete[] filePaths但这实际上allFlsArr是一个全局变量,无法删除。试试std::vector<std::wstring>不需要delete/new的。

  • 您的文件名数组太小,无法接受包含超过 300 个文件或文件夹的文件夹中的文件,再次尝试std::vector<std::wstring>可以增大大小并接受任意数量的项目!

  • 当您使用 搜索文件夹时*,Windows 会返回到您永远不应该搜索它们的额外目录 ( ., ..)。你应该跳过它们 ( if(!wcscmp(file.cFileName, L".") || !wcscmp(file.cFileName, L"..")) continue)

  • 当您应该使用时,您可以CloseHandle关闭返回的句柄。FindFirstFileFindClose

所以你可能有这样的事情:

std::vector<std::wstring> list_files( wchar_t const* folder )
{
    std::wstring root = folder;
    if( folder.back() == '*' ) folder.erase( folder.end() - 1 );
    if( folder.back() != '\\' ) folder.push_back( '\\' );

    std::vector<std::wstring> res;
    WIN32_FIND_DATA file;
    HANDLE hSearch = FindFirstFileW( folder, &file );
    if( hSearch != INVALID_HANDLE_VALUE ) {
        do {
            if( !wcscmp(file.cFileName, L".") ||
                !wcscmp(file.cFileName, L"..") )
                continue;
            res.push_back( root + file.cFileName );
            if( file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
                // search for sub folders of this folder
                std::vector<std::wstring> tmp =
                    list_files( (root + file.cFileName) + L"\\*" );
                // all all items to end of our result!
                res.insert( res.end(), tmp.begin(), tmp.end() );
            }
        } while( FindNextFileW(hSearch, &file) );
        FindClose( hSearch );
    }
    return res;
}
于 2012-10-15T16:53:49.207 回答