PDA

View Full Version : روش جستجوی فایلها ...



Mahmood_M
جمعه 25 خرداد 1386, 06:21 صبح
سلام
قصد داریم در این مقاله روش جستجوی فایلها ( بر اساس نام یا یک پسوند مشخص ) رو بررسی کنیم ...
در این مقاله تقریبا کوتاه ، توابع FindFirst و FindNext و FindClose رو بررسی میکنیم و در آخر مراحل ساخت یک برنامه جستجوگر رو پی میگیریم

تابع FindFirst :
این تابع نقطه شروع عملیات جستجو هست، این تابع دارای سه پارامتر به شرح زیر می باشد :

Path: string : مربوط به مسیر جستجوی فایل است
Attr: Integer : مربوط به مشخصات فایل است
Rec: TSearchRec : مربوط به مشخصات فایل پیدا شده است

توضیحات :
پارامتر اول ( Path ) : این پارامتر درواقع مسیری است که ما میخواهیم فایلمان را در آن جستجو نماییم ، این پارامتر از نوع String می باشد
پارامتر دوم ( Attr ) : این پارامتر درواقع مخفف کلمه Attribute ( خواص یا ویژگیها ) می باشد و مشخص مینماید که چه نوع فایلهایی جستجو شوند ، این تابع مقادیر زیر را دریافت می نماید :

faAnyFile : این مقدار مشخص میکند که هرفایلی جستجو شود ( منظور این است که مثلا هم فایلهای پنهان و هم سایر فایلها و یا فایلهای ReadOnly ، یا ... ، جزو فایلهایی باشند که جستجوی فایل مورد نظر در آنها صورت میگیرد )
faReadOnly : این مقدار مشخص میکند که جستجو فقط بین فایلهای ReadOnly انجام شود
fadirectories : برای جستجوی فولدرها یا دایرکتوریها
faHidden : این مقدار مشخص میکند که جستجو در بین فایلهای مخفی صورت بگیرد
faArchive : این مقدار مشخص میکند که جستجو در فایلهای آرشیو شده انجام شود
faSysFile : این مقدار مشخص مینماید که جستجو در فایلهای سیستمی انجام شود
faVolumeID : این مقدار مشخص مینماید که جستجو در فایلهای Volume ID صورت گیرد

توجه :
میتوانید این مقادیر را به صورت چندتایی هم بکار ببرید اما توجه کنید که هنگام به کار بردن چند تا از مقادیر بالا در تابع FindFirst ، باید بین آنها کارکتر " + " را قرار دهید :
مثلا : faHidden+faSysFile ، مشخص میکند که جستجو در بین فایلهای مخفی و فایلهای سیستمی انجام شود

پارامتر سوم ( Rec ) : این پارامتر وظیفه نگهداری اطلاعات فایل پیدا شده را برعهده دارد که از نوع TSearchRec می باشد :

type
TSearchRec = record
Time: Integer;
Size: Integer;
Attr: Integer;
Name: TFileName;
ExcludeAttr: Integer;
FindHandle: THandle;
FindData: TWin32FindData;
end;
فکر نکنم مقادیر بالا نیاز زیادی به توضیح داشته باشند ، فقط مورد آخر ( FindData ) که از نوع TWin32FindData است ، مشخصات جرئی و کاملی به به دست میدهد، مثلا " آخرین زمان دسترسی " ، " نام کوتاه فایل " و ... .

تابع FindNext :
این تابع مرحله بعدی عمل جستجو را دنبال میکند ، این تابع تنها یک پارامتر دارد که از نوع TSearchRec است ، پارامتر این تابع باید مقدار همان Rec مربوط به تابع FindFirst را گرفته و عمل جستجو را انجام دهد

اگر از این دو تابع استفاده کرده باشید ، میبینید که این توابع خروجی Integer دارند ، به این معنی که اگر این توابع با موفقیت انجام شوند ، مقدار 0 ( صفر ) و اگر با خطایی روبرو شوند مقدار ( کد ) همان خطا را برمیگردانند

FindClose :
این Procedure ، به جستجوی ما خاتمه میدهد که استفاده از آن در پایان عمل جستجو الزامی است، این Procedure هم یک پارامتر دریافت میکند که همان Rec مربوط به تابع FindFirst است

پس به طور خلاصه :
عمل جستجو با تابع FindFirst آغاز میشود ، اگر این تابع فایل مورد نظر را پیدا کرد ، مشخصات آن در یک رکورد ( Rec : TSearchRec ) نگهداری میشود ، سپس این رکورد به پارامتر تابع FindNext ارسال شده و در یک حلقه تا زمانی که تابع FindNext مقداری غیر از صفر برگرداند ، عمل جستجو ادامه می یابد و در آخر به وسیله FindClose ، عملیات جستجو خاتمه می یابد

مراحل ساخت یک برنامه جستجو گر :
یک پروژه جدید ایجاد کنید
بر روی فرم برنامه ، 2 Edit ، مثلا به نامهای AddrEdit : برای مسیر جستجو و FNameEdit : برای نام فایل مورد نظر ، قرار دهید
سپس سه عنصر CheckBox ، BitBtn و ListBox را بر روی فرم گذاشته و نام آنها را به ترتیب به SubDCheckBox ، SearchBtn و FoundsList تغییر دهید

BitBtn مربوط به دکمه ای است که عملیات را شروع میکند ، CheckBox بدین منظور است که کاربر مشخص کند که جستجو در SubFolder ها ( زیرپوشه ها یا ... ) انجام شود یا نه و ListBox هم به منظور نمایش نام فایلهای پیدا شده میباشد

برای راحتی کار از یک Procedure جدا برای جستجو استفاده میکنیم ، بدین منظور Procedure زیر را در فرم خود و در زیر عبارت Implementation قرار دهید :

procedure TMainFrm.FileSearch(const PathName, FileName : string);
var
Rec: TSearchRec;
Path: string;
begin
Path := IncludeTrailingPathDelimiter(PathName);
if FindFirst(Path + FileName, faAnyFile - faDirectory , Rec) = 0 then
begin
try
repeat
FoundsList.Items.Add(Path + Rec.Name);
Application.ProcessMessages;
until FindNext(Rec) <> 0;
finally
FindClose(Rec);
end;
end;
end;


در کد بالا ، ابتدا به وسیله تابع FindFirst به دنبال فایل میگردیم و در صورت پدا شدن ، به حلقه "Repeat-Until " رفته و تابع FindNext را تا زمانی که مقداری غیر از صفر برگرداند انجام میدهیم و در درون همان حلقه ، با هربار پیدا کردن فایل به وسیله FindNext ، یک آیتم که نام و مسیر همان فایل است را به لیست باکس اضافه مینماییم

توجه :
در کد بالا از تابع IncludeTrailingPathDelimiter استفاده شده است ، این تابع به آخر یک رشته ، کارکتر "\ " را میافزاید ، درواقع مسیر مجاز برای جستجو مسیری است که آخر آن با کارکتر " \ " بسته شده باشد ، تابع مذکور ، کارکتر گفته شده را به آخر رشته ما که همان مسیر دریافتی از کاربر است میافزاید تا مسیر معتبر باشد

جستجو در زیرپوشه ها ( SubFolders ) :
بدین منظور باید رویه بالا را به صورت تو در تو به کار گیریم ( با اندکی تغییر ) :

procedure TMainFrm.FileSearch(const PathName, FileName : string);
var
Rec: TSearchRec;
Path: string;
begin
Path := IncludeTrailingPathDelimiter(PathName);
if FindFirst(Path + FileName, faAnyFile - faDirectory , Rec) = 0 then
begin
try
repeat
FoundsList.Items.Add(Path + Rec.Name);
Application.ProcessMessages;
until FindNext(Rec) <> 0;
finally
FindClose(Rec);
end;
end;

{SubFolders}
if SubDCheckBox.Checked then
begin
if FindFirst(Path + '*.*', faDirectory, Rec) = 0 then
begin
try
repeat
if ((Rec.Attr and faDirectory) <> 0) and (Rec.Name <> '.') and (Rec.Name <> '..') then
begin
FileSearch(Path + Rec.Name, FileName);
Application.ProcessMessages;
end;
until FindNext(Rec) <> 0;
finally
FindClose(Rec);
end;
end;
end;
end;

در قسمت بعدی کد اگر چک باکس مربوطه فعال بود ، ابتدا تابع FindFirst اجرا شده و در صورت پیدا شدن فایل ، در یک حلقه بعد از بررسی نام و خصوصیات فایل ، تابع FileSearch ، اجرا میشود ، توجه کنید که تابع FileSearch یعنی همان تابعی که در آن هستیم اجرا می شود ، با این کار هر بار که پوشه ای در مسیر باشد ، مسیر جستجو ما همان پوشه شده و جستجو در آن انجام مشود . درک این قسم کمی سخت به نظر میرسد ، اما با بررسی سورس برنامه ( که ضمیمه شده است ) می توانید روش کار را به خوبی درک نمایید

چند نکته :
در کد بالا ما به آدرس ، مقدار " *.* " را اضافه کردیم ، این مقدار باعث می شود تا جستجو در پوشه های موجود در مسیر جستجو هم انجام شود ...

برای جستجوی فایلهای دارای یک پسوند خاص میتوانید تنها پسوند آن را به صورت زیر وارد نمایید :
مثلا پسوند Jpg ( فایلهای دارای این پسوند ) : " Jpg.* "

خوب ، برنامه ما کامل است ...
من سورس این برنامه ( البته با کمی تغییرات ، مثلا با امکان نمایش تعدا فایلهای پیدا شده و وضعیت جستجو و ... ) را قرار میدهم
لینک دانلود سورس :
http://www.parsaspace.com/nabegheh/Learning/FileSearch.rar

توجه :
اگر از برنامه Search ویندوز استفاده کرده باشید ، حتما دیده اید که این برنامه اگر چند تا از حروف نام فایل را دریافت کند ، باز هم آن را پیدا خواهد کرد ( مثلا اگر بنویسید : MyF ، آنگاه فایل MyFile را هم پیدا خواهد کرد ) ، برای ایجاد این ویژگی ( یا تقریبا چیزی شبیه به این ) میتوانید از مقاله قبلی ( دستکاری رشته ها (http://barnamenevis.org/showthread.php?t=70145) ) کمک بگیرید ... ( یعنی نام فایل را به وسیله آن توابع بررسی کرده و در صورت مثبت بودن نتیجه آن را نمایش دهید ... )

نکته آخر :
در تهیه این مقاله کوتاه ، از مقاله جناب Zarko Gajic در سایت About (http://delphi.about.com/od/vclusing/a/findfile.htm) کمک گرفته شده است ...
امیدوارم مفید بوده باشه ...

موفق و پیروز باشید ...

Developer Programmer
پنج شنبه 09 آبان 1387, 12:39 عصر
اما توجه کنید که هنگام به کار بردن چند تا از مقادیر بالا در تابع FindFirst ، باید بین آنها کارکتر " - " را قرار دهید
Attributes can be combined by adding (Delphi) their constants or values.
For example, to search for read-only and hidden files in addition to normal files, pass (faReadOnly + faHidden) in Delphi as the Attr parameter.