// find_file.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
测试需要的头文件
#include <conio.h>
#include <iostream>
//
x_find_file类需要的头文件
#include <windows.h>
#include <sys/stat.h>
#include <string>
#include <list>
using namespace std;
//
功能:
在指定目录及其子目录查找文件,封装了WIN32的API。
查找结果按文件创建时间排列顺序
作者:陈立福(AARON)
class x_find_file
{
private:
WIN32_FIND_DATA find_data;
HANDLE find_handle;
bool find_sub; 是否查找子目录
bool find_extent; 是否广度查找优先
bool dir_changed; 是否改变了当前查找目录
char separator; 文件目录分隔符,windows文件系统是'//'
string origin_dir; 原始目录
string current_dir; 当前查找的目录
string find_filename; 查找的文件,可含通配符
string find_result; 最后一次查找的结果,不含路径
list < string > find_dirs; 待查找的目录队列
public:
x_find_file()
{
find_sub = false; 默认不搜索子目录
find_extent = true; 默认广度搜索优先
dir_changed = false;
separator = '//'; 文件目录分隔符,windows文件系统是'//'
find_handle = INVALID_HANDLE_VALUE;
}
~x_find_file()
{
if( find_handle != INVALID_HANDLE_VALUE )
{
::FindClose( find_handle );
find_handle = INVALID_HANDLE_VALUE;
}
}
private:
不可以复制对象
x_find_file( const x_find_file & );
operator = ( const x_find_file & );
public:
功能:
读取指定目录下的子目录,不在它的子目录中继续执行查找
输入:
[dir]:执行查找的目录
[separator]:目录分隔符,默认为windows下的'//'
输出:
[sub_sirs]:查找到的子目录列表,按找到的先后顺序加入列表后面
列表原有数据不会被改变,如果查找失败(没有子目录),列表不会被改变
每个子目录项都包含[dir]
返回值:
找到子目录返回true,否则返回false
该函数被声明为static
static bool pick_sub_dirs( const string & dir, list < string > & sub_sirs,
char separator = '//' )
{
if ( dir.size() < 1 )
{
return false;
}
char directory[ 2 * MAX_PATH ];
strcpy( directory, dir.c_str() );
int dir_len = strlen( directory );
if( directory[ dir_len - 1 ] != separator )
{
directory[ dir_len ] = separator;
directory[ dir_len + 1 ] = '/0';
}
char find_string[ 2 * MAX_PATH ];
strcpy( find_string , directory );
strcat( find_string, "*.*" );
WIN32_FIND_DATA find_sub_data;
HANDLE find_sub_handle;
find_sub_handle = ::FindFirstFile( find_string, &find_sub_data);
if ( find_sub_handle == INVALID_HANDLE_VALUE )
{
return false;
}
do
{
if ( strcmp( find_sub_data.cFileName, "." )
&& strcmp( find_sub_data.cFileName, ".." ) )
{
char filename[ 2 * MAX_PATH ];
strcpy( filename, directory );
strcat( filename, find_sub_data.cFileName );
struct stat fileinfo;
if ( stat( filename, &fileinfo ) == 0 )
{
if ( fileinfo.st_mode & S_IFDIR )
{
sub_sirs.push_back( filename );
}
}
}
}
while( ::FindNextFile( find_sub_handle, &find_sub_data ) );
::FindClose( find_sub_handle );
return ( sub_sirs.size() > 0 );
}
protected:
到下一目录查找第一个文件
并改变当前查找目录为该目录
只要还有下一个目录可以继续查找
就一直执行查找
直到找到第一个文件并返回true为止
否则返回false
表示没有更多的目录可以继续查找
bool find_in_next_dir()
{
while ( find_dirs.size() > 0 )
{
更改当前查找目录为待查找目录列表的第一个目录
并将该目录移出待查找目录列表
current_dir = find_dirs.front();
find_dirs.pop_front();
dir_changed = true;
if ( find_first_file() )
{
return true;
}
}
return false;
}
public:
设置原始目录以及第一个查找的目录
void set_origin_dir( const string & dir )
{
origin_dir = dir;
current_dir = dir;
}
读取原始目录名
string get_origin_dir() const
{
return origin_dir;
}
设置并读取目录分隔符
void set_separator( char ch )
{
windows文件系统的目录分隔符是'//'
separator = ch;
}
返回类内部使用的目录分隔符
是为了在使用该类对象查找到一个文件全路径名之后
如果想分析该文件名的路径时能够使用与类内相同的目录分隔符
而不是显式的使用'//'
char get_separator() const
{
return separator;
}
设置要查找的文件名,可以包含通配符,也可以包含路径名
如果包含路径名,那么该路径是从set_origin_dir函数设定的路径开始
void set_find_filename( const string & filename )
{
find_filename = filename;
}
读取要查找的文件名
string get_find_filename() const
{
return find_filename;
}
设置及读取是否查找子目录
void set_find_sub( bool find )
{
find_sub = find;
}
bool is_find_sub() const
{
return find_sub;
}
设置及读取是否广度查找优先
void set_find_extent( bool extent )
{
find_extent = extent;
}
bool is_find_extent() const
{
return find_extent;
}
检测是否切换了当前查找目录
bool is_dir_changed() const
{
return dir_changed;
}
读取最后一次查找的文件名,不含路径
string get_filename() const
{
return find_result;
}
读取最后一次查找的文件名
包含从set_origin_dir函数设定的路径开始的路径
string get_path_filename() const
{
char filename[ 2 * MAX_PATH ];
strcpy( filename, current_dir.c_str() );
int dir_len = strlen( filename );
if ( dir_len > 0 )
{
if ( filename[ dir_len - 1 ] != separator )
{
filename[ dir_len ] = separator;
filename[ dir_len + 1 ] = '/0';
}
}
strcat( filename, find_result.c_str() );
return filename;
}
读取当前执行查找的目录
包含从set_origin_dir函数设定的路径开始的路径
string get_current_dir() const
{
return current_dir;
}
在当前目录中查找第一个文件
如果找到第一个文件就返回true
否则如果还有更多的目录可以继续查找(查找子目录)
就继续在下一目录中执行查找
一直到找到第一个文件或者没有更多的目录可以继续查找为止
如果找到第一个文件则返回true
否则返回false
执行查找时,该函数应该首先被调用并且只调用一次
否则将得不到正确的查找结果
bool find_first_file()
{
if ( current_dir.size() < 1 )
{
return false;
}
if ( find_filename.size() < 1 )
{
return false;
}
if ( find_sub )
{
如果在子目录中执行查找
则将当前目录的子目录读出并根据广度优先还是深度优先
将这些子目录相应的插入到待查找目录列表的尾部或者头部
他们在列表中的顺序就是他们被执行查找的顺序
在当前目录查找第一个文件的时候,它的子目录才被读出
list < string > sub_dirs;
if ( pick_sub_dirs( current_dir, sub_dirs, separator ) )
{
if ( find_extent )
{
find_dirs.insert( find_dirs.end(), sub_dirs.begin(), sub_dirs.end() );
}
else
{
find_dirs.insert( find_dirs.begin(), sub_dirs.begin(), sub_dirs.end() );
}
}
}
//
char directory[ 2 * MAX_PATH ];
strcpy( directory, current_dir.c_str() );
int dir_len = strlen( directory );
if( directory[ dir_len - 1 ] != separator )
{
directory[ dir_len ] = separator;
directory[ dir_len + 1 ] = '/0';
}
char find_string[ 2 * MAX_PATH ];
strcpy( find_string , directory );
strcat( find_string, find_filename.c_str() );
这种情况不应该出现的
if ( find_handle != INVALID_HANDLE_VALUE )
{
::FindClose( find_handle );
find_handle = INVALID_HANDLE_VALUE;
}
find_handle = ::FindFirstFile( find_string, &find_data );
if ( find_handle != INVALID_HANDLE_VALUE )
{
find_result = find_data.cFileName;
return true;
}
在当前目录查找失败,到下一目录继续查找
在这里有一个间接递归调用find_first_file
return find_in_next_dir();
}
在当前目录查找下一个文件
如果找则返回true
否则如果还有更多的目录可以继续查找(查找子目录)
就继续在下一目录中执行查找
一直到找到第一个文件或者没有更多的目录可以继续查找为止
如果找到第一个文件则返回true
否则返回false
bool find_next_file()
{
dir_changed = false;
if ( find_handle != INVALID_HANDLE_VALUE )
{
if ( ::FindNextFile( find_handle, &find_data ) )
{
find_result = find_data.cFileName;
return true;
}
::FindClose( find_handle );
find_handle = INVALID_HANDLE_VALUE;
}
在当前目录查找结束,则到下一目录查找
return find_in_next_dir();
}
};
//
int main(int argc, char* argv[])
{
测试
x_find_file finder;
不可以复制对象
x_find_file f1( finder );
x_find_file f2 = finder;
x_find_file f3; f3 = finder;
finder.set_origin_dir( "C://" );
finder.set_find_filename( "*.*" );
finder.set_find_sub( true );
finder.set_find_extent( false );
if ( finder.find_first_file() ) find_first_file被调用且只调用一次
{
cout << "/ncurrent_directory:/n" << finder.get_current_dir() << endl;
do
{
if ( finder.is_dir_changed() )
{
cout << "/npress 'q' to quit, else to continue..." << endl;
if ( getch() == 'q' )
{
break;
}
cout << "/ncurrent_directory:/n" << finder.get_current_dir() << endl;
}
cout << finder.get_filename() << endl;
cout << finder.get_path_filename() << endl;
}
while( finder.find_next_file() );
}
return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)