首页
社区
课程
招聘
[求助]我写了个递归遍历文件夹 小问题请教下
发表于: 2014-10-8 22:08 6740

[求助]我写了个递归遍历文件夹 小问题请教下

2014-10-8 22:08
6740
#include "stdafx.h"
#include "windows.h"
#include<iostream>
using namespace std;
void findAll(WCHAR *dir){
        wcout<<dir<<endl;
        WCHAR path[256];
        WCHAR fullpath[256]=L"";
        WCHAR *n=L"*.*";
        lstrcpy(path,dir);
        lstrcatW(path,n);
        WIN32_FIND_DATA d;
        HANDLE fp=NULL;
        fp= FindFirstFile(path,&d);
        if(fp==NULL){
                wcout<<L"打开失败"<<endl;
        }

        do{
                       
                        wsprintf(fullpath,L"%s\%s\\",dir,d.cFileName);
                        //wcout<<d.cFileName<<endl;
                       
                        if(d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){
                                if(lstrcmp(d.cFileName,L".")==0||lstrcmp(d.cFileName,L"..")==0){
                                        wcout<<L"nono"<<endl;
                                        continue;
                                }
                                        //wcout<<fullpath<<endl;
                                        findAll(fullpath);
                                       
                        }

        }while(FindNextFile(fp,&d));

}
int _tmain(int argc, _TCHAR* argv[])
{
        findAll(L"c:\\");
//        findAll(L"d:\\");
//        findAll(L"e:\\cpp\\");
//        findAll(L"f:\\");
        return 0;
}
这个 遍历c盘 为什么只遍历 program file 这个文件夹的,其他的都不会遍历
我程序有问题吗

但是我用它来搜索 c盘的某一个文件 ,只要在c盘都能搜索出来

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (12)
雪    币: 150
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
Mark
2014-10-9 00:12
0
雪    币: 78
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
do{
      wsprintf(fullpath,L"%s\%s\\",dir,d.cFileName);
1.d.cFileName如果是文件,不是文件夹的话,比如1.txt
fullpath就变成C:\1.txt\,实际搜索就变成了C:\1.txt\*.*,所以有问题
2.wsprintf(fullpath,L"%s\%s\\"   这里格式化串犯了常见错误啊  第一个%s后的\%,转移了%
是不对的,应该是\\%

修改建议
 do{      
      if(d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){
        if(lstrcmp(d.cFileName,L".")==0||lstrcmp(d.cFileName,L"..")==0){
      wsprintf(fullpath,L"%s[COLOR="Red"]\\%s[/COLOR]\\",dir,d.cFileName);
      //wcout<<d.cFileName<<endl;
          wcout<<L"nono"<<endl;
          continue;
        }
          //wcout<<fullpath<<endl;
          findAll(fullpath);
      }

  }while(FindNextFile(fp,&d));

未测试,自己改改看吧
2014-10-9 01:52
0
雪    币: 118
活跃值: (72)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
markmark
2014-10-9 06:29
0
雪    币: 3496
活跃值: (749)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
不错 学习了
2014-10-9 07:34
0
雪    币: 150
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
你的代码实在是....不工整啊..看了半天...

以下代码在VS2010下测试通过:

#include "stdafx.h"
#include "windows.h"
#include<iostream>

using namespace std;

void findAll(WCHAR *dir){

	//打印当前正在检索的路径
	wcout<<"检索目录:"<<dir<<endl;
	
	/*初始化变量*/
	//当前路径
	WCHAR path[256];
	//下一搜索路径
	WCHAR fullpath[256]=L"";
	//搜索文件过滤器
	WCHAR *n=L"*.*";

	//拼装搜索路径及搜索文件串
	lstrcpy(path,dir);
	lstrcatW(path,n);

	//搜索文件
	WIN32_FIND_DATA d;
	HANDLE fp=NULL;
	fp= FindFirstFile(path,&d);
	if(fp==NULL){
		wcout<<"打开失败"<<endl;
	}
	
	do{
		try
		{
			//如果搜索到的文件是目录
		  if(d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){
			  //如果目录名称是.或者..则过滤掉
			if(lstrcmp(d.cFileName,L".")==0||lstrcmp(d.cFileName,L"..")==0){
			  continue;
			}
			else//将目录设置为下一个递归搜索的目录
				wsprintf(fullpath,L"%s\\%s\\",dir,d.cFileName);
			//搜索目录
			findAll(fullpath); 
		  }else	//如果搜索到的文件不是目录,则当做文件处理,打印出文件全路径
		  {
			  wsprintf(fullpath,L"%s\\%s",dir,d.cFileName);
			  wcout<<"检索到文件:"<<fullpath<<endl;
 		  }
		}catch(...)
		{
			continue;
		}
	}while(FindNextFile(fp,&d));
}



int _tmain(int argc, _TCHAR* argv[])
{
	findAll(L"c:\\");
	return 0;
}


手机上网速度太慢,控制台截图我就不传了.
2014-10-9 09:56
0
雪    币: 3236
活跃值: (264)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
学习了...
2014-10-12 16:34
0
雪    币: 1363
活跃值: (139)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
看了看,没啥东西啊!!!
2014-10-26 13:22
0
雪    币: 10
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
在VS2008下写了个MFC的,用来销毁磁盘文件的,原理就是查找所有文件,找到后向文件中写入等长的数据。文件在磁盘上还是不是原来的扇区就没去研究了。受限于磁盘传输机制,多线程也没什么大作用的,就搞了个单后台线程的,对话框界面不会卡顿。

成品的软件就不贴出来了,光贴出个坯子吧。成品关键代码跟这个一模一样,成品多了一些美化、系统注册及右键菜单、判断磁盘并根据磁盘数量确定工作线程数量是否使用IOCP等非常多的细节问题。

光贴一个主对话框的源文件,熟悉MFC的同学很容易就能完成整个项目。

代码风格么,呵呵了。我比较喜欢这样的风格,因为调试的时候比较容易区分层级。

MFC很多其他东西就不贴了。
部分代码如下:


void TraversFile(CString strPath,LPVOID lpClsDlg,int nID,LPTSTR lpszFillWord,UINT nFillWordCnt,BOOL bSubDirIncld);


LRESULT CFileDestroyerDlg::OnWorkThreadDone(WPARAM wParam,LPARAM lParam)
{
	// TODO: 在此添加控件通知处理程序代码
	this ->hWorkThread = NULL;
	this ->SetDlgItemText(IDC_BUTTON_START,_T("开始"));
	::bWorking = false;
	return 0;
}

void CFileDestroyerDlg::OnBnClickedCancel()
{
	// TODO: 在此添加控件通知处理程序代码
	OnCancel();
}

void CFileDestroyerDlg::OnBnClickedButtonStart()
{
	// TODO: 在此添加控件通知处理程序代码
	if(::bWorking)
	{
		this ->SetDlgItemText(IDC_BUTTON_START,_T("开始"));
		::bWorking = false;
	}
	else
	{
		if(IDYES != this ->MessageBox(_T("注意:\n\t本操作会将所有可打开的文件进行复写操作;\n\t本操作会永久性使数据消失;\n\t本操作不可逆;\n\t\t是否继续?"),_T("警告:危险操作"),MB_YESNO | MB_ICONERROR))
		{
			return;
		}
		this ->SetDlgItemText(IDC_BUTTON_START,_T("停止"));
		::bWorking = true;
		if(NULL == (this ->hWorkThread = ::CreateThread(NULL,0,thrdWork,this,0,NULL)))
		{
			this ->MessageBox(_T("创建工作线程失败!"));
			this ->OnBnClickedButtonStart();
		}
		this ->SetDlgItemText(IDC_STATIC_FINISHCOUNT,_T("0"));
	}
}


DWORD WINAPI thrdWork(LPVOID lParam)
{
	CFileDestroyerDlg* pDlg = (CFileDestroyerDlg*)lParam;
	if(0 == pDlg ->strFilePath.GetLength())
	{
		return 0;
	}
	CString strFilePath = pDlg ->strFilePath;
	BOOL bSingleFile = pDlg ->bSingleFile;
	BOOL bSubDirIncluded = pDlg ->bSubDirIncluded;
	UINT nDestroyCount = pDlg ->nDestroyCnt;
	UINT nFillWordCntEx = pDlg ->strFillWord.GetLength() * sizeof(TCHAR);
	UINT nFillWordCnt = 0;
	LPTSTR szFillWord;
	if(nFillWordCntEx)
	{
		nFillWordCnt = nFillWordCntEx;
		szFillWord = new TCHAR[1 + nFillWordCnt / sizeof(TCHAR)];
		::wsprintf(szFillWord,_T("%s"),pDlg ->strFillWord);
	}
	else
	{
		szFillWord = _T("Zkek 文件粉碎机 Contact:775286866@qq.com\n");
		CString str = _T("Zkek 文件粉碎机 Contact:775286866@qq.com\n");

		nFillWordCnt = str.GetLength() * sizeof(TCHAR);
	}
	if(bSingleFile)
	{
		pDlg ->SetDlgItemText(IDC_STATIC_FILEPATH,_T(" 正在粉碎文件: ") + strFilePath);
		BYTE* pWrite = (BYTE*)::malloc(50 * 1024 * 1024);
		int nFillTimes = 50 * 1024 * 1024 / nFillWordCnt;
		for(int i = 0;i < nFillTimes;i++)
		{
			::memcpy(&pWrite[i * nFillWordCnt],szFillWord,nFillWordCnt);
		}
		for(UINT i = 0;i < nDestroyCount;i++)
		{
			CFile FileIn;

			if(FileIn.Open(strFilePath,CFile::modeWrite))
			{
				LONGLONG llFileLength = FileIn.GetLength();
				LONGLONG llFillTimesCnt = llFileLength / (50 * 1024 * 1024);
				FileIn.SeekToBegin();
				for(LONGLONG j = 0; j < llFillTimesCnt;j++)
				{
					FileIn.Write(pWrite,50 * 1024 * 1024);
				}
				if(llFileLength - llFillTimesCnt * 50 * 1024 * 1024)
				{
					FileIn.Write(pWrite,(llFillTimesCnt + 1) * 50 * 1024 * 1024 - llFileLength);
				}
				FileIn.Flush();
				FileIn.Close();
				CString str;
				str.Format(_T("%d"),i + 1);
				pDlg ->SetDlgItemText(IDC_STATIC_FINISHCOUNT,str);
			}
			if(!::bWorking)
			{
				break;
			}
		}
		::free(pWrite);
	}
	else
	{
		if(0 != strFilePath.Right(1).Compare(_T("\\")))
		{
			CFile FileIn;
			for(UINT i = 0;i < nDestroyCount;i++)
			{
				if(FileIn.Open(strFilePath,CFile::modeCreate | CFile::modeWrite))
				{
					FileIn.SeekToBegin();
					FileIn.Write(szFillWord,nFillWordCnt);
					FileIn.Flush();
					FileIn.Close();
				}
				else
				{
					CString strPath = pDlg ->strFilePath;
					strPath += _T("\\");
					for(UINT i = 0;i < nDestroyCount;i++)
					{
						::TraversFile(strPath,pDlg,IDC_STATIC_FILEPATH,szFillWord,nFillWordCnt,bSubDirIncluded);
						CString str;
						str.Format(_T("%d"),i + 1);
						pDlg ->SetDlgItemText(IDC_STATIC_FINISHCOUNT,str);
					}
				}
			}
		}
		else
		{
			for(UINT i = 0;i < nDestroyCount;i++)
			{
				::TraversFile(strFilePath,pDlg,IDC_STATIC_FILEPATH,szFillWord,nFillWordCnt,bSubDirIncluded);
				CString str;
				str.Format(_T("%d"),i + 1);
				pDlg ->SetDlgItemText(IDC_STATIC_FINISHCOUNT,str);
			}
		}
	}
	if(nFillWordCntEx)
	{
		delete [] szFillWord;
	}
	if(::bWorking)
	{
		pDlg ->SetDlgItemText(IDC_STATIC_FILEPATH,strFilePath + _T(" 文件粉碎完成!"));
	}
	else
	{
		pDlg ->SetDlgItemText(IDC_STATIC_FILEPATH,strFilePath + _T(" 文件粉碎停止!"));
	}
	::PostMessage(pDlg ->m_hWnd,WORK_THREAD_DONE,0,0);
	return 0;
}
void CFileDestroyerDlg::OnCancel()
{
	// TODO: 在此添加专用代码和/或调用基类
	if(::bWorking)
	{
		::bWorking = false;
	}
	this ->SetDlgItemText(IDC_EDIT_PATH,_T("清理资源..."));
	if(this ->hWorkThread)
	{
		::WaitForSingleObject(this ->hWorkThread,INFINITE);
	}

	CDialog::OnCancel();
}

void CFileDestroyerDlg::OnOK()
{
	// TODO: 在此添加专用代码和/或调用基类

	//CDialog::OnOK();
}


void CFileDestroyerDlg::OnBnClickedCheckIncldsubdir()
{
	// TODO: 在此添加控件通知处理程序代码
	this ->UpdateData();
	this ->bSingleFile = false;
	this ->UpdateData(FALSE);
}

void TraversFile(CString strPath,LPVOID lpClsDlg,int nID,LPTSTR szFillWord,UINT nFillWordCnt,BOOL bSubDirIncld)
{
	CString strPrePath = strPath;
	CString strNextPath = strPath;
	CFileFind ff;
	strPath += _T("*.*");//遍历这一级全部的目录
	int nResult = ff.FindFile(strPath);
	while(nResult && ::bWorking)
	{
		nResult = ff.FindNextFileW();
		if(ff.IsDirectory())
		{
			if(bSubDirIncld)
			{
				if(!ff.IsDots())
				{
					strNextPath += ff.GetFileName();
					strNextPath += _T("\\");
					TraversFile(strNextPath,lpClsDlg,nID,szFillWord,nFillWordCnt,bSubDirIncld);
				}
			}
		}
		else
		{
			CFile FileIn;
			if(FileIn.Open(ff.GetFilePath(),CFile::modeCreate | CFile::modeWrite))
			{
				FileIn.SeekToBegin();
				FileIn.Write(szFillWord,nFillWordCnt);
				FileIn.Flush();
				FileIn.Close();
			}
		}
		CFileDestroyerDlg* lpDlg = (CFileDestroyerDlg*)lpClsDlg;
		lpDlg ->SetDlgItemText(nID,ff.GetFilePath());
		strNextPath = strPrePath;
	}
}
void CFileDestroyerDlg::OnBnClickedButtonBrowse()
{
	// TODO: 在此添加控件通知处理程序代码 

	//CZkekFileDialog dlgFile(TRUE,NULL,NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,NULL,NULL,0,TRUE);
	CFileDialog dlgFile(TRUE);
	if(IDOK == dlgFile.DoModal())
	{
		this ->strFilePath = dlgFile.GetPathName();
		this ->UpdateData(FALSE);
	}
}



我觉得LZ的代码如果调试的话,5分钟就明白为什么了,根本没必要花同样甚至更多时间发帖。。。
2014-10-26 13:38
0
雪    币: 88
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
我使用了好多递归遍历的 ,都存在  部分文件无法打印的问题,要么也不会发帖,麻烦
2014-11-30 21:46
0
雪    币: 10
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
仅仅是打印?如果是打印字符无法显示的话会不会是ANSI和Unicode问题?试试格式化的时候指定CStringA或者CString和_T("")
2014-12-4 16:24
0
雪    币: 88
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
用它来搜索文件  是可以搜到的 ,只是全部打印,,打印一部分就结束了
2014-12-5 18:30
0
雪    币: 10
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
哈哈,这种问题最好解决,我却帮不了你。 在你的IDE里下断点调试吧,特别是条件断点,应该很有效。                                      

还有,调试的时候注意观察堆栈情况,防止因为资源不足而退出打印。

各种try catch  SEH之类的编程方法也会对你的问题有很大帮助。
TRACE,OutputDebugString之类也是极好的。
2014-12-11 10:13
0
游客
登录 | 注册 方可回帖
返回
//