Program Tip

Directory.GetFiles () 액세스가 거부 된 경우 폴더 / 파일 무시

programtip 2020. 10. 30. 20:28
반응형

Directory.GetFiles () 액세스가 거부 된 경우 폴더 / 파일 무시


선택한 디렉토리 (및 선택적으로 모든 하위 디렉토리)에있는 모든 파일 목록을 표시하려고합니다. 내가 가진 문제는 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 {}

재귀를 수동으로 수행해야합니다. 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
            }
        }
    }
}

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

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;
}

또한 방법 : 디렉터리 트리를 통해 반복을 확인하십시오 .


이를 수행하는 간단한 방법은 파일 목록과 디렉토리 대기열을 사용하는 것입니다. 메모리를 절약합니다. 재귀 프로그램을 사용하여 동일한 작업을 수행하면 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. 대기열이 비워 질 때까지 반복합니다.

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

이 기사는 GetDirectories()방법 의 결함을 인정합니다 ... :

안타깝게도 [ GetDirectories () 메서드 사용 ]이 문제가 있습니다. 이 중 핵심은 읽으려고하는 일부 폴더가 현재 사용자가 액세스 할 수 없도록 구성 될 수 있다는 것입니다. 액세스가 제한된 폴더를 무시하는 대신 메서드는 UnauthorizedAccessException을 throw합니다. 그러나 자체 재귀 폴더 검색 코드를 만들어이 문제를 피할 수 있습니다.

... 그리고 솔루션을 자세히 소개합니다.

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


이것은 질문에 답할 것입니다. 나는 하위 디렉토리를 통과하는 문제를 무시했습니다. 나는 당신이 그것을 이해했다고 가정하고 있습니다.

물론이를 위해 별도의 메서드가 필요하지는 않지만 경로가 유효한지 확인하고 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?
    }
}

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

위의 모든 솔루션은 GetFiles () 또는 GetDirectories ()에 대한 호출이 혼합 권한이있는 폴더에있는 경우 파일 및 / 또는 디렉토리를 누락합니다.


다음은 완전한 기능을 갖춘 .NET 2.0 호환 구현입니다.

버전의 List디렉토리를 건너 뛰 도록 산출 된 파일을 변경할 수도 있습니다 FileSystemInfo!

(가치주의 null!)

public static IEnumerable<KeyValuePair<string, string[]>> GetFileSystemInfosRecursive(string dir, bool depth_first)
{
    foreach (var item in GetFileSystemObjectsRecursive(new DirectoryInfo(dir), depth_first))
    {
        string[] result;
        var children = item.Value;
        if (children != null)
        {
            result = new string[children.Count];
            for (int i = 0; i < result.Length; i++)
            { result[i] = children[i].Name; }
        }
        else { result = null; }
        string fullname;
        try { fullname = item.Key.FullName; }
        catch (IOException) { fullname = null; }
        catch (UnauthorizedAccessException) { fullname = null; }
        yield return new KeyValuePair<string, string[]>(fullname, result);
    }
}

public static IEnumerable<KeyValuePair<DirectoryInfo, List<FileSystemInfo>>> GetFileSystemInfosRecursive(DirectoryInfo dir, bool depth_first)
{
    var stack = depth_first ? new Stack<DirectoryInfo>() : null;
    var queue = depth_first ? null : new Queue<DirectoryInfo>();
    if (depth_first) { stack.Push(dir); }
    else { queue.Enqueue(dir); }
    for (var list = new List<FileSystemInfo>(); (depth_first ? stack.Count : queue.Count) > 0; list.Clear())
    {
        dir = depth_first ? stack.Pop() : queue.Dequeue();
        FileSystemInfo[] children;
        try { children = dir.GetFileSystemInfos(); }
        catch (UnauthorizedAccessException) { children = null; }
        catch (IOException) { children = null; }
        if (children != null) { list.AddRange(children); }
        yield return new KeyValuePair<DirectoryInfo, List<FileSystemInfo>>(dir, children != null ? list : null);
        if (depth_first) { list.Reverse(); }
        foreach (var child in list)
        {
            var asdir = child as DirectoryInfo;
            if (asdir != null)
            {
                if (depth_first) { stack.Push(asdir); }
                else { queue.Enqueue(asdir); }
            }
        }
    }
}

참고URL : https://stackoverflow.com/questions/172544/ignore-folders-files-when-directory-getfiles-is-denied-access

반응형