📄 ch24.htm
字号:
void
TDirStack::Push(TDirInfo *DirInfo)
{
Add(DirInfo);
}
TDirInfo *TDirStack::Pop()
{
void *Temp = Items[0];
Delete(0);
return (TDirInfo *)Temp;
}
// -- TFindDirs ----------------
__fastcall TFindDirs::TFindDirs(TComponent
*AOwner, AnsiString AStartString)
: TComponent(AOwner)
{
SetStartString(AStartString); // Don't set data store directly!
FDirStack = NULL;
FOnFoundDir = NULL;
}
void __fastcall TFindDirs::SetStartString(AnsiString AStartString)
{
FStartString = AStartString;
FStartDir = ExtractFilePath(FStartString);
FFileExt = ExtractFileExt(FStartString);
}
void __fastcall TFindDirs::Initialize(void)
{
#ifdef DEBUG_FIND_DIRS
if ((fp = fopen("c:\searchdirs.txt",
"w+")) == NULL)
{
ShowMessage("Can't open debug file");
}
#endif
if (FDirStack)
delete FDirStack;
FDirStack = new TDirStack;
FCurDirectory = "";
FFileMask = "*.*";
#ifdef
DEBUG_FIND_DIRS
fprintf(fp, "%s %s %s \n", FStartDir.c_str(), FFileMask.c_str(), FFileExt.c_str());
#endif
}
__fastcall TFindDirs::~TFindDirs()
{
#ifdef DEBUG_FIND_DIRS
fclose(fp);
#endif
}
void
TFindDirs::ProcessFile(TSearchRec FileData, AnsiString FileName)
{
if (FOnFoundFile != NULL)
FOnFoundFile(FileName);
#ifdef DEBUG_FIND_DIRS
fprintf(fp, "File found: %s\n", FileName);
#endif
}
void
TFindDirs::ProcessDir(TSearchRec FileData, AnsiString DirName)
{
if (FOnFoundDir != NULL)
FOnFoundDir(DirName);
#ifdef DEBUG_FIND_DIRS
fprintf(fp, "Dir found: %s\n", DirName);
#endif
}
void
TFindDirs::FoundADir(TSearchRec *FileData)
{
AnsiString FullName;
#ifdef DEBUG_FIND_DIRS
fprintf(fp, "Dir found: %s\n", FileData->Name);
#endif
if ((FileData->Name != ".") &&
(FileData->Name
!= ".."))
{
TDirInfo *DirInfo = new TDirInfo;
DirInfo->CurDirectory = AnsiString(FCurDirectory + FileData->Name + "\\");
DirInfo->SearchRec = *FileData;
#ifdef DEBUG_FIND_DIRS
fprintf(fp,
"DirInfo: %s\n", DirInfo->SearchRec.Name);
fflush(fp);
#endif
FDirStack->Push(DirInfo);
}
}
///////////////////////////////////////
// FoundAFile
///////////////////////////////////////
void
TFindDirs::FoundAFile(TSearchRec *FileData)
{
AnsiString FullName;
if ((FFileExt == ".*") ||
(UpperCase(ExtractFileExt(FileData->Name)) == UpperCase(FFileExt)))
{
FullName = FStartDir + FCurDirectory +
FileData->Name;
ProcessFile(*FileData, FullName);
}
}
///////////////////////////////////////
// GetAllFiles
///////////////////////////////////////
void TFindDirs::GetAllFiles(AnsiString *StartDir)
{
TSearchRec FileData;
int
Info;
Info = FindFirst(StartDir->c_str(), faDirectory, FileData);
while (Info == 0)
{
if (FileData.Attr == faDirectory)
FoundADir(&FileData);
else
FoundAFile(&FileData);
Info = FindNext(FileData);
}
FindClose(&FileData.FindData);
}
///////////////////////////////////////
// SetupSearchString
///////////////////////////////////////
void TFindDirs::SetupSearchString()
{
FSearchString = FStartDir + FCurDirectory + FFileMask;
#ifdef DEBUG_FIND_DIRS
fprintf(fp, "FSearchString: %s \n", FSearchString);
#endif
}
///////////////////////////////////////
// GetNextDirectory
///////////////////////////////////////
void TFindDirs::GetNextDirectory()
{
TDirInfo *FDirInfo = FDirStack->Pop();
FCurDirectory = FDirInfo->CurDirectory;
#ifdef DEBUG_FIND_DIRS
fprintf(fp, "Next Directory: %s\n", FCurDirectory);
fflush(fp);
#endif
ProcessDir(FDirInfo->SearchRec, FStartDir
+ FCurDirectory);
delete FDirInfo;
}
BOOL TFindDirs::SetupFirstDirectory()
{
TSearchRec FileData;
AnsiString SearchStr = FStartDir + FFileMask;
int Info = FindFirst(SearchStr.c_str(), faDirectory, FileData);
FindClose(&FileData.FindData);
if (Info == 0)
{
TDirInfo *DirInfo = new TDirInfo;
DirInfo->CurDirectory = FCurDirectory;
FileData.Name = FStartDir;
DirInfo->SearchRec = FileData;
FDirStack->Push(DirInfo);
return TRUE;
}
else
return FALSE;
}
///////////////////////////////////////
// Run: FindFilesAndDirs
///////////////////////////////////////
void TFindDirs::Run(void)
{
BOOL FDone = False;
BOOL FirstTime = TRUE;
Initialize();
if (!SetupFirstDirectory())
{
ShowMessage("Invalid Search String");
return;
}
while (!FDone)
{
SetupSearchString();
if (!FirstTime)
GetAllFiles(&FSearchString);
if
(FDirStack->Count > 0)
GetNextDirectory();
else
FDone = True;
FirstTime = FALSE;
}
FDirStack->Free();
FDirStack = NULL;
}
///////////////////////////////////////
// TFindDirsList //////////////////////
///////////////////////////////////////
__fastcall TFindDirsList::TFindDirsList(TComponent *AOwner,
AnsiString AStartDir): TFindDirs(AOwner, AStartDir)
{
FFileList = new TStringList;
FFileList->Sorted = True;
FDirList = new
TStringList;
FDirList->Sorted = True;
}
__fastcall TFindDirsList::~TFindDirsList()
{
FFileList->Free();
FDirList->Free();
}
void TFindDirsList::ProcessFile(TSearchRec FileData, AnsiString FileName)
{
FFileList->Add(FileName);
}
void TFindDirsList::ProcessDir(TSearchRec FileData, AnsiString DirName)
{
FDirList->Add(DirName);
}
namespace Finddirs2
{
void __fastcall Register()
{
TComponentClass classes[2] =
{__classid(TFindDirs),
__classid(TFindDirsList)};
RegisterComponents("Unleash", classes, 1);
}
}
</FONT></PRE>
<P>The database aspects of this program are important. You will find the files used
by the program in the
<TT>Data</TT> directory on the CD that ships with this book.
As I explain in the readme file that accompanies the CD, you should set up an alias
called <TT>CUnleashed</TT> that points to these files. Needless to say, you should
recreate the data
directory on your hard drive, and should not use the read-only
directory found on the CD, but should make sure they've been copied onto your hard
drive. The <TT>DatabaseName</TT> for the <TT>TDatabase</TT> object used in my version
of the program
contains the string <TT>FileData</TT>, so you might get an error about
that alias if you try to run the program. However, you do not want to try to fix
the <TT>FileData</TT> alias, rather the one called <TT>CUnleashed</TT>. The data
module for the
program is shown in Figure 24.2.</P>
<P>To use the program, first point it to a subdirectory on your hard disk. Then type
in a file mask in the edit control at the top of the form. For example, you might
type in <TT>c:\temp\*.cpp</TT> or simply
<TT>c:\temp\*.*</TT>. Be sure to type in
the file mask. It would cause an error if you typed <TT>I:\</TT> instead of <TT>I:\*.*</TT>.
(In general, the program is not robust enough to check for many user errors.) When
you click the button at the bottom
of the program, the code iterates through all
the directories beneath the one you pointed to and finds all the files that have
the extension you designated. The program then places these files in a list database.<BR>
<BR>
<A NAME="Heading16"></A><A
HREF="24ebu02.jpg" tppabs="http://pbs.mcp.com/ebooks/0672310228/art/24/24ebu02.jpg">FIGURE 24.2.</A><FONT COLOR="#000077">
</FONT><I>The data module for the SearchDirs program.</I>
<DL>
<DT></DT>
</DL>
<BLOCKQUOTE>
<P>
<HR>
<FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>I tested the
<TT>TFindDirs</TT>
component fairly extensively. For instance, I aimed it at the root of my C drive,
which contains 1.12GB of space, with all but about 100MB used. The program ran fine
against the thousands of files on that drive. I also aimed the
component at nested
directories containing long filenames, and again it handled the challenge without
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -