2008-10-05 8 views
62

선택한 디렉토리 (및 선택적으로 하위 디렉토리)에서 발견 된 모든 파일의 목록을 표시하려고합니다. 내가 겪고있는 문제는 GetFiles() 메서드가 액세스 할 수없는 폴더를 가로 질러 오면 예외를 throw하고 프로세스가 중지된다는 것입니다.Directory.GetFiles() 액세스가 거부되었을 때 폴더/파일을 무시합니다.

이 예외를 무시하고 보호 된 폴더/파일을 무시하고 목록에 액세스 가능한 파일을 계속 추가하려면 어떻게해야합니까?

try 
{ 
    if (cbSubFolders.Checked == false) 
    { 
     string[] files = Directory.GetFiles(folderBrowserDialog1.SelectedPath); 
     foreach (string fileName in files) 
      ProcessFile(fileName); 
    } 
    else 
    { 
     string[] files = Directory.GetFiles(folderBrowserDialog1.SelectedPath, "*.*", SearchOption.AllDirectories); 
     foreach (string fileName in files) 
      ProcessFile(fileName); 
    } 
    lblNumberOfFilesDisplay.Enabled = true; 
} 
catch (UnauthorizedAccessException) { } 
finally {} 
+0

또 다른 (중복으로 표시) 질문 - http://stackoverflow.com/questions/1393178/unauthorizedaccessexception-cannot-resolve-directory-getfiles-failure?noredirect=1 –

답변

42

수동으로 재귀를 수행해야합니다. AllDirectories를 사용하지 마십시오 - 한 번에 하나의 폴더를보고 하위 디렉토리에서 파일을 가져 오십시오. 테스트되지는 않았지만 아래의 내용은 배열을 작성하는 대신 델리게이트를 사용합니다.

using System; 
using System.IO; 
static class Program 
{ 
    static void Main() 
    { 
     string path = ""; // TODO 
     ApplyAllFiles(path, ProcessFile); 
    } 
    static void ProcessFile(string path) {/* ... */} 
    static void ApplyAllFiles(string folder, Action<string> fileAction) 
    { 
     foreach (string file in Directory.GetFiles(folder)) 
     { 
      fileAction(file); 
     } 
     foreach (string subDir in Directory.GetDirectories(folder)) 
     { 
      try 
      { 
       ApplyAllFiles(subDir, fileAction); 
      } 
      catch 
      { 
       // swallow, log, whatever 
      } 
     } 
    } 
} 
+0

너무 좋은, 내가 발견하지 않은 것도 같은 이 VB.NET. 희망 만약 당신이 상관 없어 [VB.NET 여기에 번역 된] (http://stackoverflow.com/a/34924036/1197518) – Steve

+3

아직 충분하지 않습니다 : 하나의 파일을 폴더에 액세스 할 수없는 경우 GetFiles throw 내부적으로 . 따라서 전체 폴더는 처리되지 않습니다. –

2

이 질문에 답해야합니다. 나는 서브 디렉토리를 통과하는 문제를 무시했다. 나는 당신이 알아 낸 것을 가지고 있다고 가정하고있다.

물론이 방법을 사용할 필요는 없지만 경로가 유효한지 확인하고 GetFiles를 호출 할 때 발생할 수있는 다른 예외를 처리하는 것이 좋습니다.).

희망이 도움이됩니다.

private string[] GetFiles(string path) 
{ 
    string[] files = null; 
    try 
    { 
     files = Directory.GetFiles(path); 
    } 
    catch (UnauthorizedAccessException) 
    { 
     // might be nice to log this, or something ... 
    } 

    return files; 
} 

private void Processor(string path, bool recursive) 
{ 
    // leaving the recursive directory navigation out. 
    string[] files = this.GetFiles(path); 
    if (null != files) 
    { 
     foreach (string file in files) 
     { 
      this.Process(file); 
     } 
    } 
    else 
    { 
     // again, might want to do something when you can't access the path? 
    } 
} 
1

https://stackoverflow.com/a/10728792/89584 UnauthorisedAccessException 문제를 처리하는 솔루션을 참조하십시오.

위의 모든 솔루션은 GetFiles() 또는 GetDirectories()에 대한 호출이 여러 가지 권한을 가진 폴더에있는 경우 파일 및/또는 디렉터리가 누락 될 수 있습니다.

+1

GetFiles/GetDirectories와 관련된 모든 솔루션에는 동일한 문제가있을 수 있으며 따라서 조금 우아합니다. –

2

나는이 질문이 다소 오래되었다는 것을 알고 있지만, 오늘도 이와 동일한 문제가 있었으며 '폴더 재귀'솔루션을 자세히 설명하는 다음 기사를 발견했습니다.

물품합니다 ... GetDirectories() 방법의 결함을 인정 :

불행히도,이 [GetDirectories() 메소드를 사용]는 문제점이있다. 이 중 가장 중요한 점은 중 일부는 현재 사용자가 사용자가 액세스하지 못하도록 폴더를 구성 할 수 있다는 것입니다. 액세스를 제한 한 의 폴더를 무시하는 대신 UnauthorizedAccessException을 발생시킵니다. 그러나 우리는이 문제를 우회 할 수 있습니다. 우리 자신의 재귀 폴더 검색 코드를 작성하십시오.

... 다음은 세부에서 솔루션을 소개 :

http://www.blackwasp.co.uk/FolderRecursion.aspx

+0

가장 쉽게 구현할 수 있습니다. –

12

이 간단한 기능은 잘 작동하고 문제의 요구 사항을 충족합니다.

private List<string> GetFiles(string path, string pattern) 
{ 
    var files = new List<string>(); 

    try 
    { 
     files.AddRange(Directory.GetFiles(path, pattern, SearchOption.TopDirectoryOnly)); 
     foreach (var directory in Directory.GetDirectories(path)) 
      files.AddRange(GetFiles(directory, pattern)); 
    } 
    catch (UnauthorizedAccessException) { } 

    return files; 
} 
+0

그게 가장 convienent하고 투명한 방법 (y를) – derFunk

+6

불행히도 그것은 첫 번째 예외에서 중지 ... –

+1

네, 오류 처리가 누락 때문에,별로 사용하지 않습니다. c : \ 트리 전체를 검색하십시오. Windows 파일 시스템에는 관리자 권한이있는 사용자라도 액세스 권한이 충분하지 않은 영역이 많이 있습니다. 그것이 바로 주요한 도전이 여기에 관한 것입니다 (교차점과 같은 것 외에). – Philm

3

간단한 방법은 파일 목록과 디렉토리 대기열을 사용하는 것입니다. 메모리를 절약합니다. 재귀 프로그램을 사용하여 동일한 작업을 수행하면 OutOfMemory 예외가 발생할 수 있습니다. 출력 : 목록에 추가 된 파일은 위에서 아래로 (너비 우선) 디렉토리 트리에 따라 구성됩니다.

public static List<string> GetAllFilesFromFolder(string root, bool searchSubfolders) { 
    Queue<string> folders = new Queue<string>(); 
    List<string> files = new List<string>(); 
    folders.Enqueue(root); 
    while (folders.Count != 0) { 
     string currentFolder = folders.Dequeue(); 
     try { 
      string[] filesInCurrent = System.IO.Directory.GetFiles(currentFolder, "*.*", System.IO.SearchOption.TopDirectoryOnly); 
      files.AddRange(filesInCurrent); 
     } 
     catch { 
      // Do Nothing 
     } 
     try { 
      if (searchSubfolders) { 
       string[] foldersInCurrent = System.IO.Directory.GetDirectories(currentFolder, "*.*", System.IO.SearchOption.TopDirectoryOnly); 
       foreach (string _current in foldersInCurrent) { 
        folders.Enqueue(_current); 
       } 
      } 
     } 
     catch { 
      // Do Nothing 
     } 
    } 
    return files; 
} 

단계 :

  1. 인큐 큐 루프에서
  2. 의 루트는, 그것을 대기열에서 제외 목록에 해당 디렉토리에 파일을 추가하고 대기열에 하위 폴더를 추가합니다.
  3. 대기열이 비어있을 때까지 반복합니다.
관련 문제