C++下遍历文件夹,查找文件 _finddata_t _findfirst _findnext

12 篇文章 0 订阅

编写程序遍历文件夹及其子文件夹下所有文件,并输出到标准输出流或者文件流。


1. 先考虑在单层目录下,遍历所有文件。以C:\WINDOWS为例:
用到数据结构_finddata_t,文件信息结构体的指针。

struct _finddata_t
{
unsigned attrib; //文件属性
time_t time_create; //文件创建时间
time_t time_access; //文件上一次访问时间
time_t time_write; //文件上一次修改时间
_fsize_t size; //文件字节数
char name[_MAX_FNAME]; //文件名
};

文件属性是无符号整数,取值为相应的宏:_A_ARCH(存档),_A_SUBDIR(文件夹),_A_HIDDEN(隐藏),_A_SYSTEM(系统),_A_NORMAL(正常),_A_RDONLY(只读)。容易看出,通过这个结构体,我们可以得到关于该文件的很多信息。结合以下函数,我们可以将文件信息存储到这个结构体中:
C++代码
//按FileName命名规则匹配当前目录第一个文件
_findfirst(_In_ const char * FileName, _Out_ struct _finddata64i32_t * _FindData);
//按FileName命名规则匹配当前目录下一个文件
_findnext(_In_ intptr_t _FindHandle, _Out_ struct _finddata64i32_t * _FindData);
//关闭_findfirst返回的文件句柄
_findclose(_In_ intptr_t _FindHandle);

_findfirst 函数返回的是匹配到文件的句柄,数据类型为long。遍历过程可以指定文件类型,这通过FileName的赋值来实现。

例如要遍历C:\WINDOWS下的所有.exe文件

C++代码
bool transfer(string fileName = "C:\\Windows\\*.exe", int exeNum = 0) 
{ 
_finddata_t fileInfo; 
long handle = _findfirst(fileName.c_str(), &fileInfo); 

if (handle == -1L) 
{ 
    cerr << "failed to transfer files" << endl; 
    return false; 
} 

do 
{ 
    exeNum ++; 
    cout << fileInfo.name <<endl; 
} while (_findnext(handle, &fileInfo) == 0); 
cout << " .exe files' number: " << exeNum << endl; 

return true; 
} 




2. 遍历文件夹及其子文件夹下所有文件。操作系统中文件夹目录是树状结构,使用深度搜索策略遍历所有文件。用到_A_SUBDIR属性,可运行程序如下:
C++代码
void dfsFolder(string folderPath, ofstream &fout) 
{ 
_finddata_t FileInfo; 
string strfind = folderPath + "\\*"; 
long Handle = _findfirst(strfind.c_str(), &FileInfo); 

if (Handle == -1L) 
{ 
    cerr << "can not match the folder path" << endl; 
    exit(-1); 
} 
do{ 
//判断是否有子目录 
if (FileInfo.attrib & _A_SUBDIR) 
{ 
    //这个语句很重要 
    if( (strcmp(FileInfo.name,".") != 0 ) &&(strcmp(FileInfo.name,"..") != 0)) 
    { 
        string newPath = folderPath + "\\" + FileInfo.name; 
        dfsFolder(newPath, fout); 
    } 
} 
else 
{ 
    fout << folderPath << "\\" << FileInfo.name << " "; 
} 
}while (_findnext(Handle, &FileInfo) == 0); 

_findclose(Handle); 
fout.close(); 
} 



在判断有无子目录的if分支中,由于系统在进入一个子目录时,匹配到的头两个文件(夹)是"."(当前目录),".."(上一层目录)。需要忽略掉这两种情况。当需要对遍历到的文件做处理时,在else分支中添加相应的代码就好


void getFilesall(string path, vector<string>& files, vector<string>& filesname, string format) //获取指定路径下的
指定格式文件,存成列表
{
	//文件句柄  
	long   hFile = 0;
	//文件信息  
	struct _finddata_t fileinfo;  //很少用的文件信息读取结构,包含文件名称,时间,文件大小等
	string p;
	string name;
	if ((hFile = _findfirst(p.assign(path).append("\\*").c_str(), &fileinfo)) != -1) 
	{
		do
		{
			if ((fileinfo.attrib &  _A_SUBDIR))  //比较文件类型是否是文件夹
			{
				if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0) 
				{
					//files.push_back(p.assign(path).append("\\").append(fileinfo.name));
					getFilesall(p.assign(path).append("\\").append(fileinfo.name), files, filesname, format);
				}
			}
			else
			{
				string filename = fileinfo.name;
				size_t filename_size = filename.length();
				string filetype = format; //文件后缀名
				string delpath; //大小为零的文件地址
				//wstring wdelpath;
				if (filename.compare((filename_size - 4), 4, filetype) == 0) //比较文件类型
				{
					if(fileinfo.size>0) //判断文件大小,保存文件
					{
						files.push_back(p.assign(path).append("\\").append(fileinfo.name));
						filesname.push_back(name.assign(fileinfo.name));
					}
					else  //删除文件
					{
						delpath = p.assign(path).append("\\").append(fileinfo.name);
						//wdelpath = AnsiToUnicode(delpath);
						DeleteFile(delpath.c_str()); 
						cout << fileinfo.name << "为空文件,删除成功" << endl;
					}


				}
			}
		} while (_findnext(hFile, &fileinfo) == 0);  //寻找下一个,成功返回0,否则-1 循环读取路径下的文件


		_findclose(hFile);
	}
}





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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值