13

私はこの方法でフォルダからすべてのファイルを取得しようとしています:

try
{
    string[] files = Directory.GetFiles(folderBrowserDialog1.SelectedPath, "*.*", SearchOption.AllDirectories);
}
catch (UnauthorizedAccessException)
{
    throw;
}

ルートフォルダに、ユーザーがアクセスする権限を持たないフォルダが含まれている場合、UnauthorizedAccessExceptionがキャッチされ、配列が空になり、すべての再帰が失敗します。

このケースを処理し、コードが許可なく場所を無視し、許可がある場所からファイルを追加するようにするにはどうすればよいですか?

4

2 に答える 2

17

この他の投稿のSafeFileEnumeratorを参照してください。過去に SafeFileEnumerator コードを使用して成功しました。単一のファイルにアクセスできない場合に列挙全体が失われるのを防ぐため、アクセスできるファイルを反復処理できます。

編集:私が持っているバージョンは、私がリンクしたものとは少し異なるので、私が持っているバージョンを共有させてください.

public static class SafeFileEnumerator
{
    public static IEnumerable<string> EnumerateDirectories(string parentDirectory, string searchPattern, SearchOption searchOpt)
    {
        try
        {
            var directories = Enumerable.Empty<string>();
            if (searchOpt == SearchOption.AllDirectories)
            {
                directories = Directory.EnumerateDirectories(parentDirectory)
                    .SelectMany(x => EnumerateDirectories(x, searchPattern, searchOpt));
            }
            return directories.Concat(Directory.EnumerateDirectories(parentDirectory, searchPattern));
        }
        catch (UnauthorizedAccessException ex)
        {
            return Enumerable.Empty<string>();
        }
    }

    public static IEnumerable<string> EnumerateFiles(string path, string searchPattern, SearchOption searchOpt)
    {
        try
        {
            var dirFiles = Enumerable.Empty<string>();
            if (searchOpt == SearchOption.AllDirectories)
            {
                dirFiles = Directory.EnumerateDirectories(path)
                                    .SelectMany(x => EnumerateFiles(x, searchPattern, searchOpt));
            }
            return dirFiles.Concat(Directory.EnumerateFiles(path, searchPattern));
        }
        catch (UnauthorizedAccessException ex)
        {
            return Enumerable.Empty<string>();
        }
    }
}

使用例:

foreach(string fileName in SafeFileEnumerator.EnumerateFiles(folderPath, "*" + extension, SearchOption.AllDirectories))
{
    //Do something with filename, store into an array or whatever you want to do.
}
于 2012-12-19T14:42:45.697 に答える
3

FileSystemInfo オブジェクトと再帰を使用して、これを実現できます。

static List<string> files = new List<string>();

static void MyMethod() {
    DirectoryInfo dir = new DirectoryInfo(folderBrowserDialog1.SelectedPath);
    ProcessFolder(dir.GetFileSystemInfos());
}

static void ProcessFolder(IEnumerable<FileSystemInfo> fsi) {
    foreach (FileSystemInfo info in fsi) {

        // We skip reparse points 
        if ((info.Attributes & FileAttributes.ReparsePoint) == FileAttributes.ReparsePoint) {
            Debug.WriteLine("Skipping reparse point '{0}'", info.FullName);
            return;
        }

        if ((info.Attributes & FileAttributes.Directory) == FileAttributes.Directory) {
            // If our FileSystemInfo object is a directory, we call this method again on the
            // new directory.
            try {
                DirectoryInfo dirInfo = (DirectoryInfo)info;
                ProcessFolder(dirInfo.GetFileSystemInfos());
            }
            catch (Exception ex) {
                // Skipping any errors
                // Really, we should catch each type of Exception - 
                // this will catch -any- exception that occurs, 
                // which may not be the behavior we want.
                Debug.WriteLine("{0}", ex.Message);
                break;
            }
        } else {
            // If our FileSystemInfo object isn't a directory, we cast it as a FileInfo object, 
            // make sure it's not null, and add it to the list.
            var file = info as FileInfo;
            if (file != null) {
                files.Add(file.FullName);
            }
        }
    }
}

MyMethod選択したパスを受け取り、それを使用してDirectoryInfoオブジェクトを作成し、メソッドを呼び出してそれをGetFileSystemInfos()メソッドに渡しProcessFolderます。

ProcessFolderメソッドは各オブジェクトを調べ、再解析ポイントFileSystemInfoをスキップし、オブジェクトがディレクトリの場合はメソッドを再度呼び出します。それ以外の場合は、オブジェクトをオブジェクトとしてキャストし、null でないことを確認してから、ファイル名をリストに追加します。FileSystemInfoProcessFolderFileSystemInfoFileInfo

もっと読む:

于 2012-12-19T15:50:37.627 に答える