C# - Obtendo a árvore de diretórios e arquivos


  Hoje veremos como trabalhar com diretórios no sistema de arquivos usando os recursos das classes DirectoryInfo, FileInfo e FileSystemInfo. 

Vamos supor que você deseja obter uma árvore de diretórios, incluindo nomes de arquivos, estendendo-se de qualquer ponto na hierarquia de diretórios. Além disso, cada diretório ou arquivo retornado deve ser na forma de um objeto que encapsula esse item.

Isso permitirá que você realize operações nos objetos retornados, como excluir o arquivo, renomear o arquivo ou examinar/mudar seus atributos. Além disso você quer ter a habilidade de procurar por um um subconjunto específico desses itens com base em um padrão, como localizar apenas arquivos com  uma extensão.

Uma abordagem para conseguir fazer isso é usar o método de instância GetFileSystemInfos que pode recuperar todos os arquivos e diretórios na hierarquia de diretórios de qualquer ponto como uma lista enumerável.

O método GetFileSystemInfos recupera um array de objetos FileSystemInfo fortemente tipados representando arquivos e subdiretórios do diretório atual

Vejamos a seguir um exemplo prático de usar este método.

Criando o  projeto no VS 2017 Community

Usando o Visual Studio 2017 Community no menu File clique em New Project;

A seguir selecione Visual C# -> Windows Desktop;

Selecione o template Windows Forms App(.NET Framework);

Informe um nome a seu gosto. Para o exemplo vou informar WF_Doretórios;

No formulário Form1.cs inclua os seguintes controles a partir da ToolBox:

Disponha os controles conforme o leiaute da figura abaixo:

A seguir vamos definir o código do formulário.

Os namespaces usados neste projeto são:

using System;
using System.IO;
using System.Windows.Forms;
using System.Collections.Generic;

No início do formulário vamos definir duas variáveis para tratar o total de arquivos e diretórios processados:

static long arquivos = 0;
static long diretorios = 0;

No evento Click do botão btnDiretorio inclua o código que cria uma instância de FolderBrowserDialog e permite selecionar um diretório. O código define uma descrição, a pasta raiz e o botão para criar uma nova pasta:

No evento Click do botão - Processar  - obtemos a informação dos diretórios e arquivos a partir do diretório informado:

Para retornar o total de arquivos e diretórios processados vamos definir um método estático chamado ListaDiretorioArquivos():

Para obter o nome dos diretórios e arquivos estamos usando o método GetArquivosDiretorios() da classe ProcessaInfo que vamos incluir no projeto conforme o código abaixo:

using System;
using System.Collections.Generic;
using System.IO;
namespace WF_Diretorios
{
    public static class ProcessaInfo
    {
        public static IEnumerable<FileSystemInfo> GetArquivosDiretorios(string dir)
        {
            if (string.IsNullOrWhiteSpace(dir))
            {
                throw new ArgumentNullException(nameof(dir));
            }
            //define uma instância da classe DirectoryInfo
            DirectoryInfo dirInfo = new DirectoryInfo(dir);
            //define uma pilha de objetos FileSystemInfo e insere o objeto no topo da pilha
            Stack<FileSystemInfo> stack = new Stack<FileSystemInfo>();
            stack.Push(dirInfo);
            //itera enquanto for diferente de null e o contador da pilha for maior que zero
            while (dirInfo != null || stack.Count > 0)
            {
                //retorna o objeto do topo da pilha e remove
                FileSystemInfo fileSystemInfo = stack.Pop();
                DirectoryInfo subDiretorioInfo = fileSystemInfo as DirectoryInfo;
                if (subDiretorioInfo != null)
                {
                    //retorna cada elemento individualmente
                    yield return subDiretorioInfo;
                    foreach (FileSystemInfo fsi in subDiretorioInfo.GetFileSystemInfos())
                    {
                        //insere o objeto no topo da pilha
                        stack.Push(fsi);
                    }
                    dirInfo = subDiretorioInfo;
                }
                else
                {
                    //retorna cada elemento individualmente
                    yield return fileSystemInfo;
                    dirInfo = null;
                }
            }
        }
    }
}

O retorno deste método vai ser uma coleção de objetos do tipo directoryinfo e filesysteminfo a partir do qual poderemos obter o nome exibindo no listbox.

Executando o projeto e selecionando um diretório teremos o seguinte resultado:

Pegue o projeto aqui :  WF_Diretorios.zip

"Porque Deus não nos destinou para a ira, mas para a aquisição da salvação, por nosso Senhor Jesus Cristo."

Referências:


José Carlos Macoratti