Chinaunix首页 | 论坛 | 博客
  • 博客访问: 65844
  • 博文数量: 42
  • 博客积分: 1730
  • 博客等级: 上尉
  • 技术积分: 430
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-02 13:06
文章分类

全部博文(42)

文章存档

2011年(1)

2009年(41)

我的朋友

分类: C/C++

2009-11-06 11:49:00

在学习了Windows程序设计后,根据书上设计的思路,实现的递归搜索文件的程序。有什么不妥的地方,还请大家指教。
FileSearch.cpp(主程序)
 

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

//


#include "stdafx.h"
#include <Windows.h>
#include <process.h>

///////////////////////////////////////////////////////////////

// MyFinder.cpp文件


#include <stdio.h>
#include "RapidFinder.h"

void display(TCHAR *str);

UINT WINAPI FinderEntry(LPVOID lpParam)
{
    CRapidFinder* pFinder = (CRapidFinder*)lpParam;
    CDirectoryNode* pNode = NULL;    // 从m_listDir中取出的节点

    BOOL bActive = TRUE;        // 指示当前线程的状态


printf("Current threads : %d\n", pFinder->m_nThreadCount);

    // 循环处理m_listDir列表中的目录

    while(1)
    {
        // 从m_listDir列表中取出一个新的目录

        ::EnterCriticalSection(&pFinder->m_cs);
        if(pFinder->m_listDir.IsEmpty())
        {
            bActive = FALSE;
        }
        else
        {
            pNode = pFinder->m_listDir.GetHead();
            pFinder->m_listDir.Remove(pNode);

//             display(pNode->szDir);

//             E:\study\test

//             E:\study\test\a

//             E:\study\test\b

        }
        ::LeaveCriticalSection(&pFinder->m_cs);

        // m_listDir为空的话就试图在m_hDirEvent事件上等待

        if(!bActive)
        {
            // 准备进入等待状态

            ::EnterCriticalSection(&pFinder->m_cs);
            pFinder->m_nThreadCount--;
            if(pFinder->m_nThreadCount == 0) // 查看是否已经查找完毕

            {
                ::LeaveCriticalSection(&pFinder->m_cs);
                break;
            }
            ::LeaveCriticalSection(&pFinder->m_cs);

            // 进入等待状态

            ResetEvent(pFinder->m_hDirEvent);
            ::WaitForSingleObject(pFinder->m_hDirEvent, INFINITE);

            // 变成活动线程后进入下一次循环

            ::EnterCriticalSection(&pFinder->m_cs);
            pFinder->m_nThreadCount++;
            ::LeaveCriticalSection(&pFinder->m_cs);
            bActive = TRUE;
            continue;
        }


        // 在pNode指向的目录中查找文件


        WIN32_FIND_DATA fileData;
        HANDLE hFindFile;
        // 设置成X:\XXXX\*.*的格式

        if(pNode->szDir[_tcsclen(pNode->szDir)-1] != '\\')
            _tcscat(pNode->szDir, L"\\");
        _tcscat(pNode->szDir, L"*.*");
        hFindFile = ::FindFirstFile(pNode->szDir, &fileData);
        if(hFindFile != INVALID_HANDLE_VALUE)
        {
            do
            {
                if(fileData.cFileName[0] == '.')
                    continue;
                if(fileData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
                {
                    // 将搜索到的目录添加到目录列表中


                    // 为新的节点申请内存空间,设置完整的目录名称

                    CDirectoryNode* p = new CDirectoryNode;
                    _tcsncpy(p->szDir, pNode->szDir, _tcsclen(pNode->szDir)-3);
                    _tcscat(p->szDir, fileData.cFileName);
                    // 添加到列表中

                    ::EnterCriticalSection(&pFinder->m_cs);
                    pFinder->m_listDir.AddHead(p);
                    ::LeaveCriticalSection(&pFinder->m_cs);
                    // 促使一个“非活动线程”变成“活动线程”

                    ::SetEvent(pFinder->m_hDirEvent);    
                }
                else
                {
                    // 检查搜索到的文件

                    if(pFinder->CheckFile(fileData.cFileName))
                    {
                        ::EnterCriticalSection(&pFinder->m_cs);
                        ::InterlockedIncrement((long*)&pFinder->m_nResultCount);
                        ::LeaveCriticalSection(&pFinder->m_cs);
                        //printf(" %s \n", fileData.cFileName);

                        display(fileData.cFileName);
                        printf("Current threads : %d\n", pFinder->m_nThreadCount);
                    }        
                }
            }while(::FindNextFile(hFindFile, &fileData));
        }

        // 此节点保存的目录已经搜索完毕,释放内存空间,进入下次循环

        delete pNode;
        pNode = NULL;
    }

    // 促使一个搜索线程从WaitForSingleObject函数返回,并退出循环

    ::SetEvent(pFinder->m_hDirEvent);

    // 判断此线程是否是最后一个结束循环的线程,如果是就通知主线程

    if(::WaitForSingleObject(pFinder->m_hDirEvent, 0) != WAIT_TIMEOUT)
        // 如果此时pFinder->m_hDirEvent所对应的事件对象为受信状态,

        // WaitForSingleObject函数的返回值将是WAIT_OBJECT_0

    {
        // 通知主线程最后一个搜索线程即将退出,文件搜索完毕

        ::SetEvent(pFinder->m_hExitEvent);

    }
    return 0;
}

void display(TCHAR *str)
{
    int i=0;
    while (str[i])
    {
        printf("%c", str[i]);
        i++;
    }
    printf("\n");
}

int _tmain(int argc, _TCHAR* argv[])
{
    CRapidFinder* pFinder = new CRapidFinder(1);
    CDirectoryNode* pNode = new CDirectoryNode;

    // 我们只是为了测试才这样做,

    TCHAR szPath[] = L"E:\\study\\test";
    TCHAR szFile[] = L"aaa";

    // 设置参数信息

    _tcscpy(pNode->szDir, szPath);
    pFinder->m_listDir.AddHead(pNode);
    _tcscpy(pFinder->m_szMatchName, szFile);

    // 创建辅助线程并等待查找结束

    pFinder->m_nThreadCount = pFinder->m_nMaxThread;

    UINT tid;
    HANDLE h;

    for(int i=0; i<pFinder->m_nMaxThread; i++)
    {
        //AfxBeginThread(FinderEntry, pFinder);

        //CreateThread(NULL, 0, FinderEntry, pFinder, 0, &tid);

        h = (HANDLE)::_beginthreadex(NULL, 0, FinderEntry, pFinder, 0, &tid);
    }
    ::WaitForSingleObject(pFinder->m_hExitEvent, INFINITE);

    // 打印出结果

    printf(" 最终查找到的文件的个数为:%d \n", pFinder->m_nResultCount);

    CloseHandle(h);
    delete pFinder;
}



RapidFinder.h

 

///////////////////////////////////////////////////////////////

// RapidFinder.h文件


#if !defined(AFX_RAPIDFINDER_H__CB51489C_D083_4902_8FA1_F01DA07EF176__INCLUDED_)
#define AFX_RAPIDFINDER_H__CB51489C_D083_4902_8FA1_F01DA07EF176__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000


#include "../../common/_afxwin.h"

struct CDirectoryNode : public CNoTrackObject
{
    CDirectoryNode* pNext;    // CTypedSimpleList类模板要使用此成员

    TCHAR szDir[MAX_PATH];    // 要查找的目录

};

class CRapidFinder
{
public:
    CRapidFinder(int nMaxThread);
    virtual ~CRapidFinder();
    BOOL CheckFile(LPCTSTR lpszFileName);

    int m_nResultCount;                // 结果数目

    int m_nThreadCount;                // 活动线程数目

    CTypedSimpleList<CDirectoryNode*> m_listDir;    // 目录列表

    CRITICAL_SECTION m_cs;                // 关键代码段


    const int m_nMaxThread;                // 最大线程数目

    TCHAR m_szMatchName[MAX_PATH];            // 要搜索的文件

    HANDLE m_hDirEvent;                // 向m_listDir中添加新的目录后置位(受信)

    HANDLE m_hExitEvent;                // 各搜索线程将要退出时置位(受信)

};

#endif // !defined(AFX_RAPIDFINDER_H__CB51489C_D083_4902_8FA1_F01DA07EF176__INCLUDED_)


 

///////////////////////////////////////////////////////////////

// RapidFinder.cpp文件


#include "stdafx.h"
#include "RapidFinder.h"
#include <string.h>

//////////////////////////////////////////////////////////////////////

// Construction/Destruction

//////////////////////////////////////////////////////////////////////



// m_nMaxThread成员是一个const类型的变量,必须使用成员初始化列表来初始化它的值

CRapidFinder::CRapidFinder(int nMaxThread) : m_nMaxThread(nMaxThread)
{
    m_nResultCount = 0;
    m_nThreadCount = 0;
    m_szMatchName[0] = '\0';

    m_listDir.Construct(offsetof(CDirectoryNode, pNext));
    m_hDirEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
    m_hExitEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
    ::InitializeCriticalSection(&m_cs);
}

CRapidFinder::~CRapidFinder()
{
    ::CloseHandle(m_hDirEvent);
    ::CloseHandle(m_hExitEvent);
    ::DeleteCriticalSection(&m_cs);
}

BOOL CRapidFinder::CheckFile(LPCTSTR lpszFileName)
{
    TCHAR string[MAX_PATH];
    TCHAR strSearch[MAX_PATH];
    _tcscpy(string, lpszFileName);
    _tcscpy(strSearch, m_szMatchName);

    // 将字符串string和strSearch中的字符全部转化成大写

    _tcsupr(string);
    _tcsupr(strSearch);

    // 找出字符串strSearch在字符串string中第一次出现的位置

    // 如果string中不包含strSearch,strstr函数返回NULL

    if(_tcsstr(string, strSearch) != NULL)
        return TRUE;

    return FALSE;
}


阅读(1657) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~