2017-04-05 5 views
0

재귀를 사용하여 특정 유형의 파일을 검색했습니다 (예 : .pdf 파일이 여기에 사용됨). 내 재귀 알고리즘이 모든 하위 폴더를 검색합니다. 그러나 너무 많은 하위 폴더가있을 때 성능이 떨어지는 것을 발견했습니다. 서브 - 서브 - 폴더, 서브 - 서브 - 서브 폴더. 파일 검색을위한 더 나은 알고리즘이 있는지 알고 싶습니다.재귀보다 나은 파일 검색 알고리즘이 있습니까?

다음은 파일 검색을위한 재귀 코드입니다. 나는 예를

import java.io.File; 
public class FInd { 
    public static void main(String[] args) { 
     File f = new File("D:/"); 
     find(f);  
    } 
    public static void find(File f){  
     File []list = f.listFiles(); 
     try{ 
      for(int i=0;i<list.length && list.length>0;i++){  
       if(list[i].isFile() && (list[i].getName().contains(".pdf")) || 
         list[i].getName().contains(".PDF")) 
        System.out.println(list[i].getAbsolutePath()); 
       if(list[i].isDirectory()) find(list[i]); 
      } 
     }catch(Exception e){  
     } 
    } 
} 

이 코드는 파일 탐색기의 옵션을 검색 비해 다소 빠르거나 동일로 .pdf 파일을 사용하고 있습니다. 나는 그것을

입력 각 폴더, 당신은 당신이 당신의 CPU보다 더 많은 스레드를 한 경우에도 ... 새 스레드에서 시작 ... 당신은 멀티 스레딩 사용할 수있는이

+3

* 재귀 *는 알고리즘이 아니며 구현 * 선택 사항입니다. 검색 공간이있는 것 같으며 파일을 찾기 위해 탐색해야합니다. 따라서 폴더 사이에 이름과 현명한 관계가 없으면 전체 공간을 탐색해야합니다. – Arash

+1

http://stackoverflow.com/questions/4852531/find-files-in-a-folder-using-java – prasanth

+0

jdk7 이상을 사용하는 경우 Files.walkFileTree를 사용하십시오. https://docs.oracle.com/javase/ 튜토리얼/essential/io/find.html –

답변

1

반복 방법

public class Find { 
public static void main(String[] args) { 

    File f = new File("D:/"); 

    Stack stack = new Stack<File>(); 

    stack.push(f); 

    while (!stack.empty()) 
    {  
     f = (File) stack.pop(); 
     File []list = f.listFiles(); 
     try{ 
      for(int i=0;i<list.length && list.length>0;i++){  
       if(list[i].isFile() && (list[i].getName().contains(".pdf")) || 
         list[i].getName().contains(".PDF")) 
        System.out.println(list[i].getAbsolutePath()); 
       if(list[i].isDirectory()) stack.push(list[i]); 
      } 
     }catch(Exception e){  
    } 
} 
시도
+0

고마워. 이것은 도움이되었다. 그냥 작은 수정 : ** f = stack.pop(); File [] list = f2.listFiles(); ** 은 으로 대체되어야합니다. f = (File) stack.pop(); File [] list = f.listFiles(); –

+0

도움이 되었기 때문에 기쁩니다. 나는 대답을 편집 할 것이다 (나는'f' 대신에'f2'를 넣는 이유가 없다 : p). – Abdou

1

Probaply보다 빠른 알고리즘을 알고 싶어요 Windows 이후 많은 문제가 있습니다 ...

+3

성능을 향상시킬 가능성은 거의 없습니다.성능 병목 현상이 디스크에서 읽히고 디스크의 두 위치에서 동시에 읽으려고하면 성능이 저하 될 가능성이 커집니다. * (면책 조항 : SSD가 아닌 디스크라고 가정) * – Andreas

+0

또한주의해서 스레드 수를 제한해야합니다. 수천 개의 스레드를 생성하면 전체 OS가 중단 될 수 있습니다. –

+0

@JaroslawPawlak 당신이 맞습니다, 그러나 스레드가 폴더를 마친 후에 멈추는 것을 명심하십시오.) ... 대부분 폴더는 너무 길어서 (파일 내용) 스레드가 너무 빨리 닫히는 이유가 없습니다 ... – mirisbowring

2

스레딩 문제는 파일을 열 때 비용이 발생하므로 파일 탐색 + 재귀의 증가가 N 폴더/스레드.

이 루프 (재귀에 대한 고전 교체)

static boolean avoidRecursion(String target){ 
    File currentDir = new File(System.getProperty("user.home")); 
    Stack<File> dirs = new Stack<File>(); 
    dirs.push(currentDir); 

    do{ 
     for(File f : dirs.pop().listFiles()){ 
      if (f.isDirectory()) 
       dirs.push(f); 
      else{ 
       if (f.getName().equals(target)) 
        return true; 
      } 
     } 
    }while(!dirs.isEmpty()); 
    return false; 
} 

측정 두 가지 접근 방식을 사용하고있는 옵션을 선택하는 간단한 방법입니다 빠른

+0

이것은 재미있어 보입니다. 나는 그것을 시도 할 것이다 –

1

Java8 스트림을 리턴하는 Files.walk() 메소드를 사용하십시오. 병렬 스트림을 사용하여 계산을 매우 쉽게 병렬 처리 할 수 ​​있습니다.

를 사용하여 자원의 방법으로 시도에서 다음과 같은 편리한 관용구 :

시도 (스트림 발스 = Files.walk (ROOTPATH)) { ....}는 ROOTPATH에서

, 당신은 사용할 수 있습니다 Paths.get ("루트 위치") 실제로 루트 위치로 이동합니다.