代码改变世界

非递归遍历所有文件及目录:FindFirstFile,FindNextFile和FindClose

2011-06-30 23:48  x_feng  阅读(1915)  评论(1编辑  收藏  举报

都说用这三个API遍历文件效率比较高,我查了些资料,把它们封装成一个类。

#ifndef _WIN_FILEFINDENUM_H_
#define _WIN_FILEFINDENUM_H_
#include <iostream>
#include <windows.h>
#include <string>
#include <vector>
#include <queue>

class Win_FileFindEnum
{
public:
    Win_FileFindEnum(string);
    void DoErgodicFile(string);
    ~Win_FileFindEnum(){};
private:
    Win_FileFindEnum();
private:
    string rootPath;
    vector<string> FilePath;
    //vector<string> FileName;
};
Win_FileFindEnum::Win_FileFindEnum(string path):rootPath(path)
{
    DoErgodicFile(rootPath);
}
void Win_FileFindEnum::DoErgodicFile(string path)
{
    WIN32_FIND_DATAA fd;
    queue<string> AllDirectory;
    if (path[path.size() - 1] != '\\')
    {
        path = path + "\\";
    }
    AllDirectory.push(path);
    try
    {
        while(!AllDirectory.empty())
        {
            string EveryPath = AllDirectory.front();
            string tempPath = EveryPath + "*";

            HANDLE hFind = ::FindFirstFileA(tempPath.c_str(), &fd);
            if (hFind == INVALID_HANDLE_VALUE)
            {
                ::FindClose(hFind);
                return;
            }
            do
            {
                string isFile = fd.cFileName;
                if((fd.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) != 0)
                {
                    //cout<<"path"<<EveryPath<<isFile<<endl;
                    FilePath.push_back(EveryPath + isFile);
                }
                else if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0 && (isFile != "." && isFile != ".."))
                {
                    string Rp = EveryPath + fd.cFileName + "\\";
                    AllDirectory.push(Rp);
                }
            }while(::FindNextFileA(hFind, &fd));
            AllDirectory.pop();
            ::FindClose(hFind);
        }
    }catch(...){ return;}
}
#endif//_WIN_FILEFINDENUM_H_
 
以下内容为引用别人的博客------WIN32_FIND_DATA结构详解
WIN32_FIND_DATA结构描述了一个由FindFirstFile, FindFirstFileEx, 或FindNextFile函数查找到的文件信息, 

typedef struct _WIN32_FIND_DATA {

   DWORD dwFileAttributes; //文件属性

   FILETIME ftCreationTime; // 文件创建时间

   FILETIME ftLastAccessTime; // 文件最后一次访问时间

   FILETIME ftLastWriteTime; // 文件最后一次修改时间

   DWORD nFileSizeHigh; // 文件长度高32位

   DWORD nFileSizeLow; // 文件长度低32位

   DWORD dwReserved0; // 系统保留

   DWORD dwReserved1; // 系统保留

   TCHAR cFileName[ MAX_PATH ]; // 长文件名

   TCHAR cAlternateFileName[ 14 ]; // 8.3格式文件名

} WIN32_FIND_DATA, *PWIN32_FIND_DATA;

可以通过FindFirstFile()函数根据当前的文件存放路径查找该文件来把待操作文件的相关属性读取到WIN32_FIND_DATA结构中去:

WIN32_FIND_DATA ffd ;

HANDLE hFind = FindFirstFile("c:\\test.dat",&ffd);

在使用这个结构时不能手工修改这个结构中的任何数据,结构对于开发人员来说只能作为一个只读数据,其所有的成员变量都会由系统完成填写。在MSDN帮助中可以查找到关于WIN32_FIND_DATA结构的更加详细的说明。

if(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)

这个判断语句是通过 将dwFileAttributes和FILE_ATTRIBUTE_DIRECTORY做位的与运算
来判断所找到的项目是不是文件夹

因为 FindFirstFile返回的 findData 中 dwFileAttributes项的值

可能是
FILE_ATTRIBUTE_ARCHIVE
FILE_ATTRIBUTE_COMPRESSED
FILE_ATTRIBUTE_DIRECTORY
FILE_ATTRIBUTE_HIDDEN
FILE_ATTRIBUTE_NORMAL
FILE_ATTRIBUTE_OFFLINE
FILE_ATTRIBUTE_READONLY
FILE_ATTRIBUTE_SYSTEM
FILE_ATTRIBUTE_TEMPORARY
中几项的组合值

findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
的结果只能是两种:
FILE_ATTRIBUTE_DIRECTORY 非零值 ,if条件是真
0 ,if条件是假

通过 findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
可以判断 dwFileAttributes项的值中是否 FILE_ATTRIBUTE_DIRECTORY,即判断所找到的项目是不是文件夹

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/chenyongsuda/archive/2010/08/04/5788268.aspx