우리는 2022년 2월 24일부터 러시아와 전쟁 상태에 있습니다. 우크라이나가 가능한 한 빨리 승리할 수 있도록 모든 러시아 제품, 회사, 프로젝트... 모든 것을 무시하십시오.
또한 여기에서 우크라이나 군대를 도울 수 있습니다: 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
이상으로 설정하고 v1.1.7.2 이상을 사용하는 경우 4.6.2
로 설정합니다. 프로젝트 -> 속성 -> 대상 프레임워크 다음 클래스는 검색 기능을 제공합니다.
FileSearcher
및 DirectorySearcher
클래스에는 다양한 기준에 따라 검색을 실행할 수 있는 정적 메서드가 포함되어 있습니다. 이러한 메서드는 실행이 완전히 완료된 경우에만 결과를 반환합니다.string folder
- 검색 디렉터리 시작string pattern
- 경로에 있는 파일 이름과 일치하는 검색 문자열입니다. 이 매개변수는 유효한 리터럴 경로와 와일드카드(* 및 ?) 문자의 조합을 포함할 수 있지만 정규식은 지원하지 않습니다.예:
List < FileInfo > files = FileSearcher . GetFiles ( @"C:Users" , " *.txt " ) ;
하나의 스레드 방법을 사용하여 C:Users
에서 모든 *.txt
파일을 찾습니다.
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
네임스페이스의 스레드 안전 컬렉션을 사용해야 합니다.
설정할 수 있는 추가 매개변수는 2개입니다. 이는 handlerOption
및 suppressOperationCanceledException
입니다. ExecuteHandlers handlerOption
매개변수는 FilesFound 이벤트 핸들러가 실행되는 위치를 지정하는 ExecuteHandlers
열거형의 인스턴스를 나타냅니다.
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 ) ;
비동기 메서드를 사용할 때는 "await" 키워드를 사용하는 것이 좋습니다. 다음 처리 방법에서 가능한 예외를 얻을 수 있습니다. 이는 다음 코드 예제에서 설명합니다. 단순화를 위해 이전 예제의 오류 처리를 건너뛰었습니다.
예:
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 " ) ;
}
}
}
파일의 전체 이름에는 260개의 기호 Windows 제한이 있습니다. 일반적인 경우 라이브러리는 이러한 "긴" 경로를 무시합니다. 하지만 이 제한을 피하려면 다음 단계를 따라야 합니다.
<Project name>
선택하고 마우스 오른쪽 버튼 클릭 -> Add
-> New item
-> Application manifest file
. 그런 다음 이 파일의 콘텐츠를 매니페스트의 마지막 닫힌 태그 앞에 추가하세요.HKLMSYSTEMCurrentControlSetControlFileSystem
따릅니다. 그런 다음 값이 1
개인 LongPathsEnabled
매개변수(REG_DWORD 입력)를 만듭니다. 컴퓨터 성능, 현재 로딩에 따라 다르지만 일반적으로 Fast
메서드와 인스턴스 메서드 StartSearch()
간단한 단일 스레드 재귀 알고리즘보다 최소 2배 빠르게 수행됩니다.