// find_file.cpp : Defines the entry point for the console application.
//
//
#include "stdafx.h"
//// 测试需要的头文件
#include <conio.h>
#include <iostream>
#include <conio.h>
#include <iostream>
//////////////////////////////////////////////////////////////////////////
////
//// x_find_file类需要的头文件
////
#include <windows.h>
#include <sys/stat.h>
#include <string>
#include <list>
////
//// x_find_file类需要的头文件
////
#include <windows.h>
#include <sys/stat.h>
#include <string>
#include <list>
using namespace std;
//////////////////////////////////////////////////////////////////////////
//// 功能:
//// 在指定目录及其子目录查找文件,封装了WIN32的API。
//// 查找结果按文件创建时间排列顺序
//// 作者:陈立福(AARON)
//// 功能:
//// 在指定目录及其子目录查找文件,封装了WIN32的API。
//// 查找结果按文件创建时间排列顺序
//// 作者:陈立福(AARON)
class x_find_file
{
private:
WIN32_FIND_DATA find_data;
HANDLE find_handle;
{
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; //// 待查找的目录队列
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 & );
{
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 );
}
//// 功能:
//// 读取指定目录下的子目录,不在它的子目录中继续执行查找
//// 输入:
//// [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;
}
//// 并改变当前查找目录为该目录
//// 只要还有下一个目录可以继续查找
//// 就一直执行查找
//// 直到找到第一个文件并返回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;
}
//// 设置原始目录以及第一个查找的目录
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;
}
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;
}
//// 如果包含路径名,那么该路径是从set_origin_dir函数设定的路径开始
void set_find_filename( const string & filename )
{
find_filename = filename;
}
//// 读取要查找的文件名
string get_find_filename() const
{
return find_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_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;
}
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;
}
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() );
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;
}
}
//// 读取当前执行查找的目录
//// 包含从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;
}
//// 如果找到第一个文件就返回true
//// 否则如果还有更多的目录可以继续查找(查找子目录)
//// 就继续在下一目录中执行查找
//// 一直到找到第一个文件或者没有更多的目录可以继续查找为止
//// 如果找到第一个文件则返回true
//// 否则返回false
//// 执行查找时,该函数应该首先被调用并且只调用一次
//// 否则将得不到正确的查找结果
bool find_first_file()
{
if ( current_dir.size() < 1 )
{
return false;
}
if ( find_filename.size() < 1 )
{
return false;
}
if ( find_sub )
{
//// 如果在子目录中执行查找
//// 则将当前目录的子目录读出并根据广度优先还是深度优先
//// 将这些子目录相应的插入到待查找目录列表的尾部或者头部
//// 他们在列表中的顺序就是他们被执行查找的顺序
//// 在当前目录查找第一个文件的时候,它的子目录才被读出
{
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() );
}
}
}
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();
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;
//// 如果找则返回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;
{
if ( ::FindNextFile( find_handle, &find_data ) )
{
find_result = find_data.cFileName;
return true;
}
}
::FindClose( find_handle );
find_handle = INVALID_HANDLE_VALUE;
}
find_handle = INVALID_HANDLE_VALUE;
}
//// 在当前目录查找结束,则到下一目录查找
return find_in_next_dir();
}
};
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;
{
//// 测试
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;
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;
}
{
break;
}
cout << "/ncurrent_directory:/n" << finder.get_current_dir() << endl;
}
//// cout << finder.get_filename() << endl;
cout << finder.get_path_filename() << endl;
}
cout << finder.get_path_filename() << endl;
}
while( finder.find_next_file() );
}
}
return 0;
}
}