نحن في حالة حرب مع روسيا منذ 24 فبراير 2022. ولمساعدة أوكرانيا على تحقيق النصر في أقرب وقت ممكن، يرجى تجاهل جميع المنتجات والشركات والمشاريع الروسية... كل شيء.
يمكنك أيضًا مساعدة القوات المسلحة الأوكرانية هنا: https://bank.gov.ua/en/news/all/natsionalniy-bank-vidkriv-spetsrahunok-dlya-zboru-koshtiv-na-potrebi-armiyi
سوف نحرر وطننا الأم من الغزاة الروس وننقذ أوروبا من النظام الروسي العدواني اللاإنساني. أعدك.
إذا كنت ترغب في دعمي شخصيًا، فمن الممكن القيام بذلك هنا: https://ko-fi.com/VladPVS
مكتبة .NET متعددة مؤشرات الترابط التي توفر الفرصة للعثور بسرعة على الملفات أو الدلائل باستخدام معايير بحث مختلفة.
إصدار .NET Core متاح هنا.
تعتمد أداة البحث عن الملفات MIF على هذه المكتبة. يمكنك تجربتها إذا كنت تريد تقدير سرعة العمل الآن.
using FastSearchLibrary;
4.5.1
إذا كنت تستخدم الإصدار 1.1.6.1 من المكتبة أو 4.6.2
إذا كنت تستخدم الإصدار 1.1.7.2 على الأقل: Project -> Properties -> Target Framework توفر الفئات التالية وظيفة البحث:
FileSearcher
و DirectorySearcher
على أساليب ثابتة تسمح بتنفيذ البحث وفقًا لمعايير مختلفة. تُرجع هذه الأساليب النتيجة فقط عند اكتمال التنفيذ بالكامل.string folder
- ابدأ دليل البحثstring pattern
- سلسلة البحث لمطابقتها مع أسماء الملفات الموجودة في المسار. يمكن أن تحتوي هذه المعلمة على مجموعة من المسار الحرفي الصالح وأحرف البدل (* و؟)، ولكنها لا تدعم التعبيرات العادية.أمثلة:
List < FileInfo > files = FileSearcher . GetFiles ( @"C:Users" , " *.txt " ) ;
يبحث عن جميع ملفات *.txt
في C:Users
باستخدام طريقة مؤشر ترابط واحدة.
List < FileInfo > files = FileSearcher . GetFilesFast ( @"C:Users" , " *SomePattern*.txt " ) ;
يبحث عن جميع الملفات التي تطابق النمط المناسب باستخدام عدة سلاسل رسائل في تجمع مؤشرات الترابط.
Task < List < FileInfo > > task = FileSearcher . GetFilesFastAsync ( @"C:" , " a?.txt " ) ;
يبحث عن جميع الملفات التي تطابق النمط المناسب باستخدام عدة سلاسل رسائل في تجمع مؤشرات الترابط كعملية غير متزامنة.
string folder
- ابدأ دليل البحثFunc<FileInfo, bool> isValid
- المفوض الذي يحدد خوارزمية اختيار الملف.أمثلة:
Task < List < FileInfo > > task = FileSearcher . GetFilesFastAsync ( @"D:" , ( f ) =>
{
return ( f . Name . Contains ( " Pattern " ) || f . Name . Contains ( " Pattern2 " ) ) && f . LastAccessTime >= new DateTime ( 2018 , 3 , 1 ) && f . Length > 1073741824 ;
} ) ;
يبحث عن جميع الملفات التي تطابق الشروط المناسبة باستخدام عدة سلاسل رسائل في تجمع مؤشرات الترابط كعملية غير متزامنة.
يمكنك أيضًا استخدام التعبيرات العادية:
Task < List < FileInfo > > task = FileSearcher . GetFilesFastAsync ( @"D:" , ( f ) =>
{
return Regex . IsMatch ( f . Name , @".*Imagine[s_-]Dragons.*.mp3$" ) ;
} ) ;
يبحث عن جميع الملفات التي تطابق التعبير العادي المناسب باستخدام عدة مؤشرات ترابط في تجمع مؤشرات الترابط كعملية غير متزامنة.
إذا كنت ترغب في تنفيذ بعض عمليات البحث المعقدة مع الحصول على نتيجة في الوقت الفعلي، فيجب عليك استخدام مثيل لفئة FileSearcher
، التي تحتوي على العديد من الأحمال الإضافية للمنشئ. تتضمن فئة FileSearcher
الأحداث التالية:
event EventHandler<FileEventArgs> FilesFound
- يتم إطلاقه عند العثور على الجزء التالي من الملفات. يتضمن الحدث List<FileInfo> Files { get; }
الخاصية التي تحتوي على قائمة البحث عن الملفات.event EventHandler<SearchCompleted> SearchCompleted
- يتم تشغيله عند اكتمال عملية البحث أو إيقافها. يتضمن الحدث bool IsCanceled { get; }
تحتوي على قيمة تحدد ما إذا كانت عملية البحث ستتوقف عن طريق استدعاء أسلوب StopSearch()
. للحصول على إمكانية إيقاف عملية البحث، يتعين على المرء استخدام المُنشئ الذي يقبل معلمة CancellationTokenSource.مثال:
class Searcher
{
private static object locker = new object ( ) ; // locker object
private FileSearcher searcher ;
private List < FileInfo > files ;
public Searcher ( )
{
files = new List < FileInfo > ( ) ; // create list that will contain search result
}
public void StartSearch ( )
{
CancellationTokenSource tokenSource = new CancellationTokenSource ( ) ;
// create tokenSource to get stop search process possibility
searcher = new FileSearcher ( @"C:" , ( f ) =>
{
return Regex . IsMatch ( f . Name , @".*[iI]magine[s_-][dD]ragons.*.mp3$" ) ;
} , tokenSource ) ; // give tokenSource in constructor
searcher . FilesFound += ( sender , arg ) => // subscribe on FilesFound event
{
lock ( locker ) // using a lock is obligatory
{
arg . Files . ForEach ( ( f ) =>
{
files . Add ( f ) ; // add the next part of the received files to the results list
Console . WriteLine ( $" File location: { f . FullName } , n Creation.Time: { f . CreationTime } " ) ;
} ) ;
if ( files . Count >= 10 ) // one can choose any stopping condition
searcher . StopSearch ( ) ;
}
} ;
searcher . SearchCompleted += ( sender , arg ) => // subscribe on SearchCompleted event
{
if ( arg . IsCanceled ) // check whether StopSearch() called
Console . WriteLine ( " Search stopped. " ) ;
else
Console . WriteLine ( " Search completed. " ) ;
Console . WriteLine ( $" Quantity of files: { files . Count } " ) ; // show amount of finding files
} ;
searcher . StartSearchAsync ( ) ;
// start search process as an asynchronous operation that doesn't block the called thread
}
}
لاحظ أن جميع معالجات أحداث FilesFound
ليست آمنة لمؤشر الترابط، لذا لمنع فقدان النتائج، يجب عليك استخدام كلمة lock
الأساسية كما ترون في المثال أعلاه أو استخدام مجموعة مؤشرات الترابط الآمنة من مساحة الاسم System.Collections.Concurrent
.
هناك معلمتان إضافيتان يمكن ضبطهما. هذه هي handlerOption
suppressOperationCanceledException
. تمثل معلمة ExecuteHandlers handlerOption
مثيل تعداد ExecuteHandlers
الذي يحدد مكان تنفيذ معالجات الأحداث FilesFound:
InCurrentTask
أنه سيتم تنفيذ معالجات الأحداث FileFound
في تلك المهمة التي تم العثور على الملفات فيها.InNewTask
أنه سيتم تنفيذ معالجات الأحداث FilesFound
في مهمة جديدة. القيمة الافتراضية هي InCurrentTask
. ومن الأفضل في معظم الحالات. يجب استخدام قيمة InNewTask
فقط إذا قام المعالجون بتنفيذ عمل معقد جدًا يستغرق الكثير من الوقت، على سبيل المثال، تحليل كل ملف تم العثور عليه. تحدد المعلمة bool suppressOperationCanceledException
ما إذا كان من الضروري منع OperationCanceledException. إذا كانت قيمة معلمة suppressOperationCanceledException
false
وتم استدعاء أسلوب StopSearch()، فسيتم طرح OperationCanceledException
. في هذه الحالة عليك معالجة الاستثناء يدويًا. إذا كانت قيمة معلمة suppressOperationCanceledException
true
وتم استدعاء طريقة StopSearch()، فستتم معالجة OperationCanceledException
تلقائيًا ولن تحتاج إلى التقاطها. القيمة الافتراضية true
.
مثال:
CancellationTokenSource tokenSource = new CancellationTokenSource ( ) ;
FileSearcher searcher = new FileSearcher ( @"D:Program Files" , ( f ) =>
{
return Regex . IsMatch ( f . Name , @".{1,5}[Ss]ome[Pp]attern.txt$" ) && ( f . Length >= 8192 ) ; // 8192b == 8Kb
} , tokenSource , ExecuteHandlers . InNewTask , true ) ; // suppressOperationCanceledException == true
يمكن لفئتي FileSearcher
و DirectorySearcher
البحث في دليل واحد فقط (وفي جميع الدلائل الفرعية بالتأكيد) ولكن ماذا لو كنت تريد إجراء البحث في عدة أدلة في نفس الوقت؟
بالطبع، يمكنك إنشاء بعض مثيلات فئة FileSearcher
(أو DirectorySearcher
) وتشغيلها في وقت واحد، ولكن أحداث FilesFound
(أو DirectoriesFound
) ستحدث لكل مثيل تقوم بإنشائه. كقاعدة عامة، فإنه غير مريح. تهدف الفئتان FileSearcherMultiple
و DirectorySearcherMultiple
إلى حل هذه المشكلة. وهي تشبه FileSearcher
و DirectorySearcher
لكن يمكنها تنفيذ البحث في عدة أدلة. الفرق بين FileSearcher
و FileSearcherMultiple
هو أن مُنشئ فئة Multiple
يقبل قائمة الدلائل بدلاً من دليل واحد.
مثال:
List < string > folders = new List < string >
{
@"C:UsersPublic" ,
@"C:WindowsSystem32" ,
@"D:Program Files" ,
@"D:Program Files (x86)"
} ; // list of search directories
List < string > keywords = new List < string > { " word1 " , " word2 " , " word3 " } ; // list of search keywords
FileSearcherMultiple multipleSearcher = new FileSearcherMultiple ( folders , ( f ) =>
{
if ( f . CreationTime >= new DateTime ( 2015 , 3 , 15 ) &&
( f . Extension == " .cs " || f . Extension == " .sln " ) )
{
foreach ( var keyword in keywords )
if ( f . Name . Contains ( keyword ) )
return true ;
}
return false ;
} , tokenSource , ExecuteHandlers . InCurrentTask , true ) ;
يوصى بشدة باستخدام الكلمة الأساسية "انتظار" عند استخدام أي طريقة غير متزامنة. فهو يسمح بالحصول على استثناءات محتملة من طريقة متابعة المعالجة، والتي سيتم توضيحها في مثال التعليمات البرمجية التالي. لقد تم تخطي معالجة الأخطاء في الأمثلة السابقة من أجل البساطة.
مثال:
using System ;
using System . Collections . Generic ;
using System . Diagnostics ;
using System . IO ;
using System . Text . RegularExpressions ;
using System . Threading ;
using FastSearchLibrary ;
namespace SearchWithAwait
{
class Program
{
private static object locker = new object ( ) ;
private static List < FileInfo > files ;
private static Stopwatch stopWatch ;
static void Main ( string [ ] args )
{
string searchPattern = @".mp4$" ;
StartSearch ( searchPattern ) ;
Console . ReadKey ( true ) ;
}
private static async void StartSearch ( string pattern )
{
stopWatch = new Stopwatch ( ) ;
stopWatch . Start ( ) ;
Console . WriteLine ( " Search has been started. n " ) ;
files = new List < FileInfo > ( ) ;
List < string > searchDirectories = new List < string >
{
@"C:" ,
@"D:"
} ;
FileSearcherMultiple searcher = new FileSearcherMultiple ( searchDirectories , ( f ) =>
{
return Regex . IsMatch ( f . Name , pattern ) ;
} , new CancellationTokenSource ( ) ) ;
searcher . FilesFound += Searcher_FilesFound ;
searcher . SearchCompleted += Searcher_SearchCompleted ;
try
{
await searcher . StartSearchAsync ( ) ;
}
catch ( AggregateException ex )
{
Console . WriteLine ( $" Error occurred: { ex . InnerException . Message } " ) ;
}
catch ( Exception ex )
{
Console . WriteLine ( $" Error occurred: { ex . Message } " ) ;
}
finally
{
Console . Write ( " n Press any key to continue... " ) ;
}
}
private static void Searcher_FilesFound ( object sender , FileEventArgs arg )
{
lock ( locker ) // using of the lock is mandatory
{
arg . Files . ForEach ( ( f ) =>
{
files . Add ( f ) ; // add the next part of the received files to the results list
Console . WriteLine ( $" File location: { f . FullName } n Creation.Time: { f . CreationTime } n " ) ;
} ) ;
}
}
private static void Searcher_SearchCompleted ( object sender , SearchCompletedEventArgs arg )
{
stopWatch . Stop ( ) ;
if ( arg . IsCanceled ) // check whether StopSearch() called
Console . WriteLine ( " Search stopped. " ) ;
else
Console . WriteLine ( " Search completed. " ) ;
Console . WriteLine ( $" Quantity of files: { files . Count } " ) ; // show amount of finding files
Console . WriteLine ( $" Spent time: { stopWatch . Elapsed . Minutes } min { stopWatch . Elapsed . Seconds } s { stopWatch . Elapsed . Milliseconds } ms " ) ;
}
}
}
يوجد حد Windows يبلغ 260 رمزًا على الاسم الكامل للملفات. في الحالات الشائعة، ستتجاهل المكتبة مثل هذه المسارات "الطويلة". ولكن إذا كنت تريد التحايل على هذا القيد، فيجب عليك اتباع الخطوات التالية:
<Project name>
في مستكشف الحلول، وانقر بزر الماوس الأيمن فوق -> Add
-> New item
-> Application manifest file
. ثم أضف محتوى هذا الملف إلى البيان قبل آخر علامة مغلقة.HKLMSYSTEMCurrentControlSetControlFileSystem
ثم قم بإنشاء المعلمة LongPathsEnabled
(اكتب REG_DWORD) بقيمة 1
. يعتمد ذلك على أداء جهاز الكمبيوتر الخاص بك، والتحميل الحالي، ولكن عادةً ما يتم تنفيذ الطرق Fast
وطريقة المثيل StartSearch()
على الأقل مرتين أسرع من الخوارزمية العودية البسيطة ذات الخيط الواحد.