没看到能打的,遍历目录并读取目录下的文件列表。(C语言,SDK)

遍历目录并读取目录下的所有文件,这个功能经常用,也简单,很多年前就看过网上的代码,感觉写复杂了,而且还浪费栈,发文的人说会“爆栈”(而且还不是一个人)。当时看到那些代码就觉得写的不好,不过觉得无关痛痒没有发博文。

N年过去,遇到类似的情况,有点忍不住,这么简单的东西。今天专门去搜索了网上(摆渡和谷歌上面的代码,包括StackOverflow上面的代码,不禁说出周星星电影《破坏之王》里面断水流大师兄的那段话。
找到的代码,几乎都是类似的,代码长,真浪费内存,速度又慢,还没有错误判断。
找一个稍好的例子。
bool ListDirectoryContents(const wchar_t *sDir)

    WIN32_FIND_DATA fdFile; 
    HANDLE hFind = NULL; 


    wchar_t sPath[2048]; 


    //Specify a file mask. *.* = We want everything! 
    wsprintf(sPath, L"%s\\*.*", sDir); 


    if((hFind = FindFirstFile(sPath, &fdFile)) == INVALID_HANDLE_VALUE) 
    { 
        wprintf(L"Path not found: [%s]\n", sDir); 
        return false; 
    } 


    do
    { 
        //Find first file will always return "."
        //    and ".." as the first two directories. 
        if(wcscmp(fdFile.cFileName, L".") != 0
                && wcscmp(fdFile.cFileName, L"..") != 0) 
        { 
            //Build up our file path using the passed in 
            //  [sDir] and the file/foldername we just found: 
            wsprintf(sPath, L"%s\\%s", sDir, fdFile.cFileName); 


            //Is the entity a File or Folder? 
            if(fdFile.dwFileAttributes &FILE_ATTRIBUTE_DIRECTORY) 
            { 
                wprintf(L"Directory: %s\n", sPath); 
                ListDirectoryContents(sPath); //Recursion, I love it! 
            } 
            else{ 
                wprintf(L"File: %s\n", sPath); 
            } 
        }
    } 
    while(FindNextFile(hFind, &fdFile)); //Find the next file. 


    FindClose(hFind); //Always, Always, clean things up! 


    return true; 

网上的都是类似的,还有说遍历复杂云云,其实不复杂,代码短并且省内存(这里主要是省栈),速度更快。

这样写的时候,想想就发现,有两个地方可以优化,第一,局部变量sPath,这里占用内存大,而且还每次都复制一次,速度慢;第二、局部变量fdFile,这个占用内存也大......
又大又慢,所以会爆栈。

我现在记事本写一个比这个好的(N年前就这么写了,还有牛人说不需要递归,当时想了一下,我也实现了)。
UINT ListFiles(const TCHAR *pathname, UINT pathnamelength, UINT pathnamesize, WIN32_FIND_DATA *pfd)

    HANDLE hfind; 

    UINT l;

    UINT result = 0;


   if (pathnamelength > 0 && pathname[pathnamelength - 1] != _T('\\'))

{
pathname[pathnamelength++] = _T('\\');

}

pathname[pathnamelength+0] = _T('*');

pathname[pathnamelength+1] = _T('.');

pathname[pathnamelength+2] = _T('*');

pathname[pathnamelength+3] = _T('\0');

hfind = FindFirstFile(pathname, pfd);
if(hfind != INVALID_HANDLE_VALUE) 
{
    do
    { 
        // 这里可以优化的,留给有追求的人优化,不过这里不是关键
        if(_tcscmp(pfd->cFileName, _T(".")) != 0 && _tcscmp(pfd->cFileName, _T("..")) != 0) 

        {

            l = _tcslen(pfd->cFileName);

            // 避免越界

           if (pathnamelength + l < pathnamesize)

            {

                    // 重用了占用内存的pathname和pfd

                    _tcscpy(pathname + pathnamelength, pfd->cFileName);

                    // 已经获取了文件信息,爱干嘛干嘛去

                   if(pfd->dwFileAttributes &FILE_ATTRIBUTE_DIRECTORY) 

                    { 
                            result += ListFiles(pathname, pathnamelength + l, pathnamesize, pfd);
                    } 
                    else{ 
                    result++;

                    } 

            }

        }
    } while(FindNextFile(hfind, pfd));

    FindClose(hfind);

}



 return (result); 

我在网上看到linux下遍历的代码也大同小异,也没有优化,都可以类似这么写的。

不骄傲,一个小代码而已,N年前就会这么写了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值