• 设为首页
  • 收藏本站
  • 积分充值
  • VIP赞助
  • 手机版
  • 微博
  • 微信
    微信公众号 添加方式:
    1:搜索微信号(888888
    2:扫描左侧二维码
  • 快捷导航
    福建二哥 门户 查看主题

    用递归写Win32的文件夹遍历

    发布者: 忻慕2619 | 发布时间: 2025-6-27 16:25| 查看数: 65| 评论数: 0|帖子模式

    文件夹遍历技术是一种非常有用的技术,在文件的搜索以及杀毒软件中都使用了这种技术。以下我将讨论如何在Win32下实现这种技术。
    文件夹遍历技术的核心就是使用递归算法,关于递归算法,我这里就不多介绍了,不明白的朋友请找出谭先生的《C程序设计》参阅相关内容。
    以下是我的算法伪代码:
    1. <font face="新宋体"><font color="#0000ff">void</font> function( LPCTSTR lpszPath )<br />{<br />    开始查找;<br />    <font color="#0000ff">if</font> ( 没有找到文件 )<br />        <font color="#0000ff">return</font>;<br />    <font color="#0000ff">do</font><br />    {<br />        <font color="#0000ff">if</font> ( 找到的文件是目录 )<br />            function( 找到的目录 );<br />        <font color="#0000ff">else</font><br />            对文件进行操作;<br />    } <font color="#0000ff">while</font> ( 查找下一个文件并成功 );<br />}</font>
    复制代码

    实现这个算法所需要用到的API函数以及结构体有:
         
    • FindFirstFile;   
    • FindNextFile;   
    • WIN32_FIND_DATA。
    在此我假定你已经明白了以上函数及结构体的用法,now let's begin。
    现在我来编写开始查找的代码。在这之前,我先假定函数参数lpszPath传入的路径格式为X:(根目录)或Xir(非根目录),因为Win32程序设计中通常使用的就是这种路径格式。你一定注意到了,如果路径是根目录,它的后边有一个路径分隔符“”,反之则没有。那么我在写代码的时候必须对这两种情况分别处理。这段代码如下:
    1. <font face="新宋体">TCHAR szFind[MAX_PATH];<br />lstrcpy( szFind, lpszPath );<br /><font color="#0000ff">if</font> ( !IsRoot( szFind ) ) <font color="#008000">// IsRoot是我自己编写的函数,若参数是根目录,则返回true</font><br />    lstrcat( szFind, "" );<br />lstrcat( szFind, "*.*" ); <font color="#008000">// 找所有文件</font><br />WIN32_FIND_DATA wfd;<br />HANDLE hFind = FindFirstFile( szFind, &wfd );<br /><font color="#0000ff">if</font> ( INVALID_HANDLE_VALUE == hFind ) <font color="#008000">// 如果没有找到或查找失败</font><br />    <font color="#0000ff">return</font>;</font>
    复制代码
    下面我将讨论的是如果找到了文件,该怎么办。不过在此之前,请你进入MS-DOS方式,并输入dir回车,你看到了什么?

    是的,DOS是不会说假话的,不像Windows一样总把重要的东西隐藏起来不让你看到——如果你所在的不是根目录,你将会看到“.”与“..”这两个目录——这是在资源管理器中看不到的。从DOS时代走过的朋友们大抵都明白吧,一个点代表的是当前目录,两个点代表的是上一级目录。那么我在处理信息时,就一定得把它们两个过滤出去,原因我在下面解释。do-while段的代码如下:
    1. <font face="新宋体"><font color="#0000ff">do</font><br />{<br />    <font color="#0000ff">if</font> ( lstrcmp( wfd.cFileName, _T(".") ) == 0 || lstrcmp ( wfd.cFileName, _T("..") ) == 0 )<br />        <font color="#0000ff">continue</font>; <font color="#008000">// 过滤这两个目录</font><br />    <font color="#0000ff">if</font> ( wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )<br />    {<br />        TCHAR szFile[MAX_PATH];<br />        <font color="#0000ff">if</font> ( IsRoot( lpszPath ) )<br />            wsprintf( szFile, "%s%s", lpszPath, wfd.cFileName );<br />        <font color="#0000ff">else</font><br />            wsprintf( szFile, "%s\%s", lpszPath, wfd.cFileName );<br />        function( szFile ); <font color="#008000">// 如果找到的是目录,则进入此目录进行递归</font><br />    }<br />    <font color="#0000ff">else</font><br />    {<br />        <font color="#008000">// 对文件进行操作</font><br />    }<br />} <font color="#0000ff">while</font> ( FindNextFile( hFind, &wfd ) );<br />FindClose( hFind ); <font color="#008000">// 关闭查找句柄</font></font>
    复制代码

    现在我来解释为什么要把那两个带点的目录过滤出去。如你所见,如果找到的是目录,那么进入此目录进行递归——那么若是当前目录呢?答案很明显,如果不对其进行过滤,那么程序将进入“当前目录”进行递归。是了,如是将导致递归无休止地进行下去。
    算法就这么多了,由于这是一个极其耗费系统资源的算法,因此你在程序中用到它的时候,最好将其放到一个单独的线程中运行,否则将会导致你的程序在查找过程中没有任何响应。
    如果你还有更好的算法,请贴在下面我们一起讨论。
    附:IsRoot函数源码
    1. <font face="新宋体">BOOL IsRoot( LPCTSTR lpszPath )<br />{<br />    TCHAR szRoot[4];<br />    wsprintf( szRoot, "%c:", lpszPath[0] );<br />    <font color="#0000ff">return</font> ( lstrcmp( szRoot, lpszPath ) == 0 );<br />}</font>
    复制代码


    来源:https://www.jb51.net/hack/16328.html
    免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有账号?立即注册

    ×

    最新评论

    QQ Archiver 手机版 小黑屋 福建二哥 ( 闽ICP备2022004717号|闽公网安备35052402000345号 )

    Powered by Discuz! X3.5 © 2001-2023

    快速回复 返回顶部 返回列表