C# - LINQ : Calculando o tamanho dos arquivos em uma pasta


No artigo de hoje vamos calcular o tamanho de um arquivo selecionado, o tamanho total da pasta e o tamanho médio dos arquivos de uma pasta usando LINQ.


A LINQ já é um velho conhecido dos que utilizam a plataforma .NET e dispensa apresentações, como eu já escrevi dezenas de artigos sobre a LINQ, se desejar mais detalhes veja as referências no final do artigo.
 
A Language-Integrated Query (LINQ) adiciona recursos de consulta ao C# e utiliza uma sintaxe unificada independentemente do tipo de dados. 

Vamos então por a LINQ para trabalhar...

Recursos usados:

Criando o projeto no Visual Studio 2017 Community

Abra o VS 2017 Community e clique em New Project;

Selecione a linguagem Visual C# -> Windows Classic Desktop  e o template Windows Forms App(.NET Framework);

Informe o nome CShp_LINQ e clique no botão OK;

A seguir inclua no formulário Form1.vb os seguintes controles:

Disponha os controles no formulário segundo o leiaute da figura abaixo:

Namespaces usados no formulário :

using System;
using System.Data;
using System.IO;
using System.Linq;
using System.Windows.Forms;

Declare a variável arquivos no início do formulário:

 string[] arquivos;

Definindo o Código do Formulário

Vamos definir o código do controles, eventos e métodos que vamos usar no formulário para poder implementar as funcionaldidades que desejamos.

1 - No evento Click do botão para selecionar a pasta inclua o código abaixo:

       private void btnSelecionaPasta_Click(object sender, EventArgs e)
        {
            try
            {
                //define o nome da pasta selecionada
                fbdlg1.SelectedPath = txtPasta.Text;
                if (fbdlg1.ShowDialog() == DialogResult.OK)
                {
                    //exibe no textbox
                    txtPasta.Text = fbdlg1.SelectedPath;
                }
                //obtem os arquivos da pasta selecionada
                arquivos = Directory.GetFiles(fbdlg1.SelectedPath);

                //exibe os arquivos no ListBox
                foreach (string f in Directory.GetFiles(fbdlg1.SelectedPath))
                    this.lbArquivos.Items.Add(f);
            }
            catch
            {
                throw;
            }
        }

Este código usa o componente FolderBrowserDialog para selecionar uma pasta e a seguir o método GetFiles para obter os arquivos da pasta exibindo-os no ListBox usando um laço foreach.

2 - Código do evento SelectedIndexChanged que é disparado quando selecionamos um arquivo do ListBox:

       private void lbArquivos_SelectedIndexChanged(object sender, EventArgs e)
        {
            //habilita o botão e exibe o groupbox
            grpArquivos.Visible = true;
            btnAgruparPorExtensao.Enabled = true;
            //calcula o total de arquivos na pasta
            lblArquivos.Text = arquivos.Count().ToString() + " Arquivos encontrados";
            //obtem o nome e caminho da pasta
            string caminhoPasta = lbArquivos.GetItemText(lbArquivos.SelectedItem);
            //calcula o tamanho do arquivo selecionado
            long tamanho = new System.IO.FileInfo(caminhoPasta).Length;
            lblTamanhoArquivo.Text = FormataExibicaoTamanhoArquivo(tamanho);
            //calcula o tamanho médio dos arquivos da pasta
            double media = arquivos.Select(file => new FileInfo(file).Length).Average();
            lblTamanhoMedioArquivos.Text = FormataExibicaoTamanhoArquivo((long)Math.Round(media / 10, 1));
            //calcula o tamanho total da pasta e subpastas
            DirectoryInfo infoDiretorio = new DirectoryInfo(fbdlg1.SelectedPath);
            long tamanhoDoDiretorio = TamanhoTotalDiretorio(infoDiretorio, true);
            lblTamanhoTotalPasta.Text = FormataExibicaoTamanhoArquivo(tamanhoDoDiretorio);
        }

Neste código usamos dois métodos :

  1. FormataExibicaoTamanhoArquivo - Formata a exibição do tamanho do arquivo;

  2. TamanhoTotalDiretorio - Calcula o tamanho total do diretório;

a-) Abaixo temos o código do método FormataExibicaoTamanhoArquivo :

       // Retorna o tamanho do arquivo para um tamanho
        // O formato padrão é "0.### XB", Ex: "4.2 KB" ou "1.434 GB"
        public string FormataExibicaoTamanhoArquivo(long i)
        {
            // Obtém o valor absoluto
            long i_absoluto = (i < 0 ? -i : i);
            // Determina o sufixo e o valor
            string sufixo;
            double leitura;
            if (i_absoluto >= 0x1000000000000000) // Exabyte
            {
                sufixo = "EB";
                leitura = (i >> 50);
            }
            else if (i_absoluto >= 0x4000000000000) // Petabyte
            {
                sufixo = "PB";
                leitura = (i >> 40);
            }
            else if (i_absoluto >= 0x10000000000) // Terabyte
            {
                sufixo = "TB";
                leitura = (i >> 30);
            }
            else if (i_absoluto >= 0x40000000) // Gigabyte
            {
                sufixo = "GB";
                leitura = (i >> 20);
            }
            else if (i_absoluto >= 0x100000) // Megabyte
            {
                sufixo = "MB";
                leitura = (i >> 10);
            }
            else if (i_absoluto >= 0x400) // Kilobyte
            {
                sufixo = "KB";
                leitura = i;
            }
            else
            {
                return i.ToString("0 bytes"); // Byte
            }
            // Divide por 1024 para obter o valor fracionário
            leitura = (leitura / 1024);
            // retorna o número formatado com sufixo
            return leitura.ToString("0.### ") + sufixo;
        }

b-) A seguir o código do método TamanhoTotalDiretorio :

        private long TamanhoTotalDiretorio(DirectoryInfo dInfo, bool includeSubDir)
        {
            //percorre os arquivos da pasta e calcula o tamanho somando o tamanho de cada arquivo
            long tamanhoTotal = dInfo.EnumerateFiles().Sum(file => file.Length);
            if (includeSubDir)
            {
                tamanhoTotal += dInfo.EnumerateDirectories().Sum(dir => TamanhoTotalDiretorio(dir, true));
            }
            return tamanhoTotal;
        }

Este método vai percorrer cada arquivo da pasta e somar o tamanho do arquivo para calcular o total da pasta. É uma função que poderá ser otimizada pois é um pouco lenta.

3-) Finalmente temos o código do método Click do botão - Contar e agrupar arquivos por extensão :

  private void btnAgruparPorExtensao_Click(object sender, EventArgs e)
        {
            //agrupa os arquivos da pasta por extensão
            var arquivosAgrupadosPorExtensao = arquivos.Select(arq => Path.GetExtension(arq).TrimStart('.').ToLower())
                                                                    .GroupBy(x => x, (ext, extCnt) => 
                                                                    new { Extensao = ext, Contador = extCnt.Count() });
            //percorre o resultado e exibe os valores
            foreach (var arquivo in arquivosAgrupadosPorExtensao)
                lbArquivos.Items.Insert(0, arquivo.Contador + " arquivos(s) com extensão ." + arquivo.Extensao);
        }

Neste código a LINQ agrupa os arquivos por extensão e a seguir inclui o resultado no início do ListBox usando o método - lbArquivos.Items.Insert(0,..)

Executando o projeto iremos obter o seguinte resultado:

Assim, revimos os conceitos básicos do LINQ e realizamos algumas operações com arquivos mostrando a versatilidade do LINQ.

Pegue o projeto completo aqui :   CShp_LINQ.zip

Porque Deus enviou o seu Filho ao mundo, não para que condenasse o mundo, mas para que o mundo fosse salvo por ele.
Quem crê nele não é condenado; mas quem não crê já está condenado, porquanto não crê no nome do unigênito Filho de Deus.

João 3:17,18

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?

Quer aprender a criar aplicações Web Dinâmicas usando a ASP .NET MVC 5 ?

  Gostou ?   Compartilhe no Facebook   Compartilhe no Twitter

Referências:


José Carlos Macoratti